Test Spec: CLI Parse-Error Output¶
Document Control¶
| Field | Value |
|---|---|
| Status | Implemented |
| Design doc | docs/design/cli-parse-errors.md |
| Test file | tests/test_cli_entry_point.py |
| Primary test area | CLI, output contract |
Test Objectives¶
Prove that argument-parsing failures honour the requested output format through the installed canarchy console script, which is the only route that exercises the argv=None entry path. Every test in this spec runs the console script as a real subprocess; calling canarchy.cli.main([...]) in-process passes an explicit argument list and cannot observe the defect this spec guards (#519).
Coverage Requirements¶
- each parse-failure class — unrecognised option, unknown subcommand, missing required argument, invalid typed value — emits a canonical JSON envelope when
--jsonis requested --jsonlemits the same envelope as a single JSONL record- conflicting output flags resolve by fixed precedence, in either order
- text output stays human-readable and is not valid JSON
- successful commands and runtime (post-parse) errors are unchanged
- every parse failure exits 1
Requirement Traceability¶
| Requirement ID | Description summary | Covered by test IDs |
|---|---|---|
REQ-CLIERR-01 |
resolve argv before detecting output format | TEST-CLIERR-01, TEST-CLIERR-02, TEST-CLIERR-03, TEST-CLIERR-04, TEST-CLIERR-05 |
REQ-CLIERR-02 |
--json parse-failure envelope |
TEST-CLIERR-01, TEST-CLIERR-02, TEST-CLIERR-03, TEST-CLIERR-04 |
REQ-CLIERR-03 |
--jsonl parse-failure envelope |
TEST-CLIERR-05 |
REQ-CLIERR-04 |
all parse-failure classes covered | TEST-CLIERR-01, TEST-CLIERR-02, TEST-CLIERR-03, TEST-CLIERR-04 |
REQ-CLIERR-05 |
exit code 1 for parse failures | TEST-CLIERR-01, TEST-CLIERR-02, TEST-CLIERR-03, TEST-CLIERR-04, TEST-CLIERR-05, TEST-CLIERR-06, TEST-CLIERR-07 |
REQ-CLIERR-06 |
text mode stays readable | TEST-CLIERR-07 |
REQ-CLIERR-07 |
fixed precedence for conflicting output flags | TEST-CLIERR-06 |
REQ-CLIERR-08 |
successful output unchanged | TEST-CLIERR-08, TEST-CLIERR-09 |
Test Cases¶
TEST-CLIERR-01 — Unrecognised option honours --json¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy stats --unknown-option --json` as a subprocess
Then the system shall exit with code 1
And stdout shall parse as a single JSON object with `ok` false and `command` `"cli"`
And the first error shall have code `INVALID_ARGUMENTS` and a non-empty hint
And the error message shall contain `unrecognized arguments: --unknown-option`
Fixture: none.
TEST-CLIERR-02 — Unknown subcommand honours --json¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy bogus-subcommand --json` as a subprocess
Then the system shall exit with code 1
And stdout shall parse as a JSON error envelope with code `INVALID_ARGUMENTS`
And the error message shall contain `invalid choice: 'bogus-subcommand'`
Fixture: none.
TEST-CLIERR-03 — Missing required argument honours --json¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy decode --json` as a subprocess
Then the system shall exit with code 1
And stdout shall parse as a JSON error envelope with code `INVALID_ARGUMENTS`
And the error message shall contain `the following arguments are required: --dbc`
Fixture: none.
TEST-CLIERR-04 — Invalid typed value honours --json¶
Given the `canarchy` console script is installed and `tests/fixtures/sample.candump` is present
When the operator runs `canarchy stats --file sample.candump --top notanint --json` as a subprocess
Then the system shall exit with code 1
And stdout shall parse as a JSON error envelope with code `INVALID_ARGUMENTS`
And the error message shall contain `argument --top: invalid int value: 'notanint'`
Fixture: tests/fixtures/sample.candump.
TEST-CLIERR-05 — Parse failure honours --jsonl¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy stats --unknown-option --jsonl` as a subprocess
Then the system shall exit with code 1
And stdout shall contain exactly one non-empty line
And that line shall parse as the canonical `INVALID_ARGUMENTS` error envelope
Fixture: none.
TEST-CLIERR-06 — Conflicting output flags use fixed precedence¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy stats --unknown-option` with `--json --jsonl`, `--jsonl --json`, or `--text --json`
Then the system shall exit with code 1
And stdout shall parse as a JSON error envelope with code `INVALID_ARGUMENTS`
And the error message shall report that the second output flag is not allowed with the first
Fixture: none.
TEST-CLIERR-07 — Text mode stays readable¶
Given the `canarchy` console script is installed for the test interpreter
When the operator runs `canarchy stats --unknown-option` with no output flag or with `--text`
Then the system shall exit with code 1
And stdout shall begin with `command: cli`
And stdout shall contain the `error: INVALID_ARGUMENTS: ...` and `hint: ` lines
And stdout shall not parse as JSON
Fixture: none.
TEST-CLIERR-08 — Successful command output is unchanged¶
Given the `canarchy` console script is installed and `tests/fixtures/sample.candump` is present
When the operator runs `canarchy stats --file sample.candump --json` as a subprocess
Then the system shall exit with code 0
And stdout shall parse as a JSON result envelope with `ok` true and `command` `"stats"`
And `data.total_frames` shall be greater than zero
Fixture: tests/fixtures/sample.candump.
TEST-CLIERR-09 — Runtime error envelope is unchanged¶
Given the `canarchy` console script is installed and the capture path does not exist
When the operator runs `canarchy stats --file <missing> --json` as a subprocess
Then the system shall exit with a nonzero code
And stdout shall parse as a JSON error envelope with `command` `"stats"`
Fixture: a temporary directory providing a path that does not exist.
Fixtures And Environment¶
tests/fixtures/sample.candump— small candump capture used by the typed-value and success cases.- The console script is located next to
sys.executable; if it is absent (a source checkout run without installing the project) the tests skip rather than fall back to an in-process call, because an in-process call would not exercise the behaviour under test. - The suite-wide isolation fixtures in
tests/conftest.pyredirectHOMEand stripCANARCHY_*from the environment, and the subprocesses inherit that environment, so no operator configuration reaches these runs.
Not Tested¶
- argparse's
--helpand--versionoutput, which argparse prints and exits 0 for before any CANarchy code runs. - The wording of argparse's failure messages — they are passed through verbatim and are a Python implementation detail.
- The in-process
execute_commandpath used by the REPL and TUI: it always receives an explicit argument list, and its parse-failure envelope is covered intests/test_cli.py.