82 lines
4.1 KiB
Markdown
82 lines
4.1 KiB
Markdown
# shout
|
|
|
|
Transcript-based shell integration test runner. Rust.
|
|
|
|
## Commands
|
|
|
|
- `cargo test` — run tests (integration tests in `tests/shout.rs`)
|
|
- `cargo build` — build the binary
|
|
- `cargo run -- test [files...]` — run shout CLI
|
|
- `-u, --update` — rewrite `.shout` files with actual output
|
|
- `-k, --keep` — keep temp directories after run
|
|
- `--clean-env` — start with empty environment
|
|
- `--path <path>` — prepend to `$PATH` (repeatable)
|
|
- `--timeout <dur>` — per-command timeout (default `10s`)
|
|
- `-t, --filter <pattern>` — only run files whose path contains `<pattern>`
|
|
- `-v, --verbose` — print each command as it runs
|
|
- `--port-from <n>` — auto-assign `$PORT` starting from n (default `5400`)
|
|
- `--parallel` — run files in parallel
|
|
|
|
## Architecture
|
|
|
|
- `src/main.rs` — CLI entry point, arg parsing, file discovery, `run_one` orchestration
|
|
- `src/parse.rs` — parses `.shout` files into `ShoutFile` (list of `Command`), also `parse_setup`
|
|
- `src/run.rs` — executes commands via `/bin/sh`, captures output with sentinels
|
|
- `src/matching.rs` — wildcard-aware output matching and diff generation
|
|
- `src/format.rs` — evaluates pass/fail, formats failures and summary
|
|
- `src/update.rs` — rewrites `.shout` files with actual output (`--update` mode)
|
|
- `src/duration.rs` — parses duration strings (`10s`, `500ms`, `1m`)
|
|
- `web/index.html` — web documentation page
|
|
|
|
## .shout file format
|
|
|
|
- `$ ` prefix = command to execute
|
|
- Lines between commands = expected output (stdout+stderr merged)
|
|
- `...` on its own line = multi-line wildcard (matches zero or more lines)
|
|
- `...` inline = matches any characters on that line
|
|
- `[N]` on last line of expected output = assert exit code N
|
|
- `[*]` = assert any non-zero exit code; default expects 0
|
|
- `#` at start of line = comment (not executed, no output expected)
|
|
- `$#` also works as comment (legacy syntax)
|
|
- `\#` in expected output = literal line starting with `#`
|
|
- `#` after a command = comment (stripped); `#` in expected output is literal
|
|
- `@env KEY=VALUE` before first command = set environment variable
|
|
- `@teardown <command>` before first command = run command after all test commands
|
|
- Runs regardless of pass/fail
|
|
- Teardown failures produce warnings but don't affect test results
|
|
- Can appear in both `.shout` files and setup files
|
|
- `@setup path.shout` before first command = prepend commands (and `@env`) from another file
|
|
- Setup files use a plain format: each line is a command (no `$ ` prefix), `#` lines are comments, blank lines ignored
|
|
- Setup files can contain `@env`, `@teardown`, and `@def` directives but not `@setup` (no nesting)
|
|
- User file `@env` overrides setup file `@env`
|
|
- Setup command failures abort the test with an error
|
|
- `@def name body` before first command = define a macro
|
|
- If a command matches `name` exactly, `body` is substituted before execution
|
|
- Backslash `\` at end of line continues the body onto the next line
|
|
- Allowed in both `.shout` files and setup files
|
|
- User file `@def` overrides setup file `@def` with the same name
|
|
- Each file runs in a fresh temp dir with a single `/bin/sh` session
|
|
- `$HOME` and `$SHOUT_DIR` are set to the temp dir automatically
|
|
- `$SHOUT_SOURCE_DIR` is set to the directory containing the `.shout` file
|
|
- `$SHOUT_PROJECT_DIR` is set to `cwd` where `shout` was invoked
|
|
- stdout and stderr are merged (`exec 2>&1`)
|
|
|
|
## New feature checklist
|
|
|
|
1. `src/parse.rs` — update types (`Directive`, `ShoutFile`, `Command`) and both parsers (`parse` + `parse_setup`)
|
|
2. `src/main.rs` — wire up the parsed result in `run_one` (directive resolution, command merging, result handling)
|
|
3. `tests/*.shout` — integration test file exercising the feature end-to-end
|
|
4. `CLAUDE.md` — update `.shout file format` section
|
|
5. `README.md` — update Directives section
|
|
6. `web/index.html` — add or update a section on the website
|
|
7. Run `cargo test` to verify
|
|
|
|
## Style
|
|
|
|
- Rust 2024 edition
|
|
- No OOP — plain functions and structs/enums
|
|
- Integration tests in `tests/shout.rs`, example `.shout` files in `tests/`
|
|
- Never use `unsafe`
|
|
- Keep dependencies to the bare minimum.
|
|
- If you must use a dependency, use the lightest-weight version.
|