ty
This commit is contained in:
parent
edce909525
commit
56d982db17
189
SPEC.md
189
SPEC.md
|
|
@ -1,189 +0,0 @@
|
||||||
# shout
|
|
||||||
|
|
||||||
A transcript-based shell integration test runner.
|
|
||||||
|
|
||||||
## Format
|
|
||||||
|
|
||||||
A `.shout` file is a plain text transcript of a shell session. Lines starting
|
|
||||||
with `$ ` are commands. Everything after — until the next `$` or end of file
|
|
||||||
— is the expected output (stdout and stderr combined).
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev new "add auth"
|
|
||||||
created draft 1 "add auth"
|
|
||||||
|
|
||||||
$ dev save
|
|
||||||
saved draft 1 (v1)
|
|
||||||
```
|
|
||||||
|
|
||||||
Blank lines within expected output are significant. Trailing newline on the
|
|
||||||
file is ignored.
|
|
||||||
|
|
||||||
### Comments
|
|
||||||
|
|
||||||
`#` after a command is a comment and is stripped before execution. Comments
|
|
||||||
in expected output are matched literally.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev new "add auth" # create a draft from timeline HEAD
|
|
||||||
created draft 1 "add auth"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Wildcards
|
|
||||||
|
|
||||||
A `...` on its own line in expected output matches any number of lines
|
|
||||||
(including zero).
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev log
|
|
||||||
...
|
|
||||||
draft 1 "add auth"
|
|
||||||
```
|
|
||||||
|
|
||||||
A `...` inline matches any sequence of characters on that line.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev status
|
|
||||||
draft 1 "add auth" (v...)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment
|
|
||||||
|
|
||||||
Each `.shout` file runs in a fresh temporary directory. The directory is
|
|
||||||
created before the first command and removed after the last (unless
|
|
||||||
`--keep` is passed).
|
|
||||||
|
|
||||||
All commands in a file run in a single shell session (`/bin/sh`), so `cd`,
|
|
||||||
`export`, and other shell state persists between commands.
|
|
||||||
|
|
||||||
The following environment variables are set for every command:
|
|
||||||
|
|
||||||
| Variable | Value |
|
|
||||||
|---|---|
|
|
||||||
| `HOME` | the temp directory |
|
|
||||||
| `PATH` | inherited from host (or prepended via `--path`) |
|
|
||||||
| `CUE_DIR` | the temp directory |
|
|
||||||
|
|
||||||
All other environment variables are inherited from the host unless explicitly
|
|
||||||
cleared with `--clean-env`.
|
|
||||||
|
|
||||||
### Exit codes
|
|
||||||
|
|
||||||
By default, a non-zero exit code fails the test regardless of output. To
|
|
||||||
assert a specific exit code, append `[N]` on the last line of expected output:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev rm
|
|
||||||
error: draft 1 has children. use dev rm -f to cascade.
|
|
||||||
[1]
|
|
||||||
```
|
|
||||||
|
|
||||||
`[*]` accepts any non-zero exit code without asserting the value.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CLI
|
|
||||||
|
|
||||||
```
|
|
||||||
shout [options] [files|dirs...]
|
|
||||||
```
|
|
||||||
|
|
||||||
If no files are given, shout runs all `*.shout` files in the current directory
|
|
||||||
and subdirectories. Each command in each shout file is run sequentially
|
|
||||||
(unless `--parallel` is passed).
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
| Flag | Description |
|
|
||||||
|---|---|
|
|
||||||
| `--update` / `-u` | Rewrite expected output in-place with actual output |
|
|
||||||
| `--keep` / `-k` | Keep temp directories after run (printed to stderr) |
|
|
||||||
| `--clean-env` | Start with empty environment (only `PATH` and `CUE_DIR` set) |
|
|
||||||
| `--path <path>` | Prepend `<path>` to `PATH` (repeatable) |
|
|
||||||
| `--timeout <dur>` | Per-command timeout, e.g. `500ms`, `10s`, `1m` (default: `10s`) |
|
|
||||||
| `--verbose` / `-v` | Print each command as it runs |
|
|
||||||
| `--parallel` | Run files in parallel (implies all files run regardless of failures) |
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
Passing files print a single `.` per file. Failing files print a unified diff:
|
|
||||||
|
|
||||||
```
|
|
||||||
FAIL tests/auth.shout
|
|
||||||
|
|
||||||
$ dev rm
|
|
||||||
- error: draft 1 has children. use dev rm -f to cascade.
|
|
||||||
+ error: draft 1 has dependents. use dev rm -f to cascade.
|
|
||||||
[1]
|
|
||||||
```
|
|
||||||
|
|
||||||
Summary line at the end:
|
|
||||||
|
|
||||||
```
|
|
||||||
12 passed, 1 failed in 340ms
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Update mode
|
|
||||||
|
|
||||||
`--update` rewrites the expected output sections of each `.shout` file with the
|
|
||||||
actual output from the run. Commands, comments, and whitespace are preserved.
|
|
||||||
Wildcard lines are left in place if the actual output matches them; they are
|
|
||||||
only replaced if the match fails.
|
|
||||||
|
|
||||||
This makes it safe to run `shout --update` routinely after intentional output
|
|
||||||
changes — review the diff, commit if correct.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File layout
|
|
||||||
|
|
||||||
```
|
|
||||||
tests/
|
|
||||||
auth.shout
|
|
||||||
drafts.shout
|
|
||||||
stack.shout
|
|
||||||
```
|
|
||||||
|
|
||||||
No special directory structure is required. `.shout` files can live anywhere.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation notes
|
|
||||||
|
|
||||||
- Bun + TypeScript
|
|
||||||
- Each file runs in a single `/bin/sh` session via `Bun.spawn`
|
|
||||||
- Stdout and stderr merged (same as a terminal)
|
|
||||||
- Shell state (`cd`, `export`, etc.) persists across commands within a file
|
|
||||||
- Commands are fed to the shell sequentially; output between commands is
|
|
||||||
captured by delimiting with sentinel `echo` statements
|
|
||||||
- shout exits `0` if all tests pass, `1` if any fail
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dev new "add auth"
|
|
||||||
created draft 1 "add auth"
|
|
||||||
|
|
||||||
$ echo 'export function auth() {}' > auth.ts
|
|
||||||
$ dev save
|
|
||||||
saved draft 1 (v1)
|
|
||||||
|
|
||||||
$ echo 'export function auth(token: string) {}' > auth.ts
|
|
||||||
$ dev save
|
|
||||||
saved draft 1 (v2)
|
|
||||||
|
|
||||||
$ dev status
|
|
||||||
draft 1 "add auth" (v2)
|
|
||||||
modified: (none)
|
|
||||||
|
|
||||||
$ dev new "add db"
|
|
||||||
created draft 2 "add db"
|
|
||||||
|
|
||||||
$ dev rm 1
|
|
||||||
error: draft 1 has children. use dev rm -f to cascade.
|
|
||||||
[1]
|
|
||||||
```
|
|
||||||
Loading…
Reference in New Issue
Block a user