Skip to content

qmstrace results

TL;DR

qmstrace results REPORT... matches pytest JUnit reports or TRX files, read as one, to scanned automated tests, and follows their verifies links to requirements — directly, or through the test cases they run. It shows requirement verdicts, the test cases on the way, missing results, shared tests and unmatched entries. Exit 0 means a results view was produced, even if tests failed. The report's commit is not verified.

Synopsis

Usage: qmstrace results [OPTIONS] {REPORT...}

  Match reports to scanned tests and their explicit verifies links.

  Each report is pytest JUnit XML or a TRX file (dotnet test --logger trx); its
  root element decides which. Several reports are read as one, in any order: a
  run in two of them counts once, with its worst verdict. Informational: failing
  tests and partial matches still exit 0. Unmatched entries are listed; reports
  with no matches exit 2. Relative report paths start at -C or the current
  directory, not the discovered repo root. A report outside the repo is shown by
  its file name. The reports' commit is not verified.

Arguments:
  REPORT...  Pytest JUnit XML reports or TRX files, read as one —
             TestResults/*.trx.  [required]

Options:
  -C PATH  Run as if qmstrace had been started in PATH, as with git -C. Before
           or after the command.
  --help   Show this message and exit.

A relative report path starts at the invocation directory, or the directory supplied with -C, even when qmstrace discovers the repository above it. -C works before or after the command. An explicitly supplied report is read even when Git ignores it or it is outside the repository. A report is shown by its path from the repository root, or, outside the repository, by its file name alone; two reports that would be shown alike are refused, as is a report given twice.

Several reports

Several reports are read as one, so qmstrace results TestResults/*.trx reads each test project's file in one run. A run reported in two files is one run: it keeps the worst verdict and counts once as a duplicate, as a repeated entry within one file does. The order the reports are given in changes nothing. With more than one report, the header lists each one with its entry count, so a missing or truncated file is visible, and every run that did not pass names the reports it was in. Each run also keeps the sha256 of its reports' bytes. One report prints the same view as before.

Matching and counts

The report's root element decides how it is read: testsuite or testsuites is pytest JUnit XML, and TeamTest's TestRun is a TRX file. Any other root is refused, as are DTDs, entities and external references.

JUnit. The reader accepts pytest's default output in either xunit1 or xunit2 format, including nested suites and XML namespaces. Matching is exact: the report's classname and test name without parameters must identify one scanned pytest test. Class methods retain their class names. Parameter IDs may contain brackets.

TRX, as dotnet test --logger trx writes it. Matching is exact on the class and method the result's test definition names: the class namespace-qualified, a nested class joined to its outer class with +. The DisplayName plays no part in matching, so rewording a test does not unmatch it; renaming or moving its method does. A result's name is its testName, so each row of a [Theory] is a run of one automated test. Only the class, the method, the name, the outcome and the first line of an error message are read: a TRX file's paths, machine and user names, output, stack traces and attachments are never shown. With several test projects, dotnet test writes a TRX for each: give results every one of them.

Custom class-name prefixes, identity collisions and entries with missing identity attributes are reported; qmstrace does not guess a match.

An automated test is a scanned test function or test method. A reported run is a distinct full (classname, name) identity, including parameters. Duplicate XML entries for the same full identity are combined using the worst verdict and counted explicitly. This includes pytest's separate entries for a body failure and teardown error. Duplicate entries do not establish retry history. Global counts count each automated test once, even when requirement rows overlap.

A partial set of parameter variants does not prove every possible variant ran.

Verdicts

Subject Rule
Automated test with reported runs Worst of fail, skip, pass, in that order
Automated test absent from the report no-result
Test case, or requirement, that automated tests reach Worst of their verdicts: fail, no-result, skip, pass
Test case, or requirement, that no automated test reaches untested

XML error and failure both mean fail. Expected failures and unexpected passes follow pytest's XML representation: qmstrace adds no separate xfail policy. In a TRX file, Passed means pass and NotExecuted means skip; any other outcome — Failed, Timeout, Aborted, Inconclusive — or none means fail, and the outcome is shown beside the run.

A verdict follows verifies links: from an automated test to what it verifies, and on through a test case to what the test case verifies. A requirement's row names the test cases its verdict came through. A test case no automated test runs adds nothing: it neither passes a requirement nor holds one back. A design element carries Satisfies, not verifies, so a test of a design element does not imply a verdict for its requirements; such tests and test cases are listed apart. Nonpassing test details name the affected runs and show outcome messages. A shared test names the other items it verifies.

Inspection and analysis requirements appear separately. Their linked test results, if any, do not change their verification method or establish approval.

Partial report example

This miniature service report contains a skipped design test, a shared failing test with a teardown error, an absent test, and an entry that no longer matches a scanned test:

report: report.xml
  6 XML entries · 5 reported runs (distinct full identities)
  matched: 4 runs of 3 automated tests · scanned: 4 automated tests · unmatched: 1 run identities
  matched against the current working tree — report commit NOT VERIFIED
  a partial parameter set does not prove every possible variant ran
  baselines: judged from reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines: no matching reachable local tag — nothing frozen locally
  change requests: NOT VERIFIED — ../ledger/change-requests is unavailable; fresh citations are verified at the ledger's import
  1 duplicate XML entries combined by full identity; retry attempts are not inferred

requirements — direct verifies links only:
  REQ-SVC-01  pass      1 automated tests · 2 runs — A call carries a key · requirement · docs/req/service-srs.md:12
  REQ-SVC-02  fail      2 automated tests · 1 runs — Records survive a restart · requirement · docs/req/service-srs.md:21
    fail      tests/integration/test_store.py::test_a_record_survives_a_restart · 1 runs · shared: also verifies DSN-SVC-02
      fail: test_a_record_survives_a_restart (error, failure)
        error: teardown could not close store
        failure: record missing after restart
    no-result tests/integration/test_store.py::test_a_restart_loses_no_accepted_record · 0 runs

inspection / analysis — no verification or approval is established by this report:
  REQ-SVC-03 — The record format is written down · Verify-by: inspection · requirement · docs/req/service-srs.md:28
    no linked automated tests

tests without a direct requirement target — no requirement verdict inferred:
    skip      tests/unit/test_keys.py::TestTheKeyCheck::test_it_runs_before_any_handler · 1 runs · verifies DSN-SVC-01
      skip: test_it_runs_before_any_handler (skipped)
        skipped: handler fixture unavailable

unmatched report entries:
  pass      ('tests.removed.test_old', 'test_old') · 1 XML entries · no scanned automated test matches this identity
  Fix: check report provenance and scan patterns; use default pytest JUnit names.

result: 3 matched automated tests · 4 matched runs · 1 unmatched run identities · exit 0 (informational) — report commit NOT VERIFIED; this repo's tests only

A partial report retains recognized results and lists unmatched identities. A requirement with a known failure remains fail even when another directly linked test has no result.

Through test cases

In a project with a Test Specification, the automated tests name the test case they run, and the test case names what it verifies. Run from the product repo, the view reads the ledger's test cases with their own links — read for verdicts only, never counted as this repo's links:

report: report.xml
  5 XML entries · 5 reported runs (distinct full identities)
  matched: 5 runs of 5 automated tests · scanned: 5 automated tests · unmatched: 0 run identities
  matched against the current working tree — report commit NOT VERIFIED
  a partial parameter set does not prove every possible variant ran
  baselines: judged from reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines: no matching reachable local tag — nothing frozen locally
  change requests: ../ledger/change-requests (1 readable; 0 malformed) — current working tree, not pinned

requirements — verdicts along verifies links, from automated tests directly or through test cases:
  REQ-SVC-01  pass      via TC-SVC-01.1 · 2 automated tests · 2 runs — A call carries a key · requirement, in sibling ledger — not pinned · ../ledger/docs/req/service-srs.md:5
    via TC-SVC-01.1  pass · 2 automated tests
  REQ-SVC-02  pass      1 automated tests · 1 runs — Records survive a restart · requirement, in sibling ledger — not pinned · ../ledger/docs/req/service-srs.md:12

test cases that reach no requirement — no requirement verdict inferred:
  TC-SVC-01.2  pass · 1 automated tests · verifies DSN-SVC-01 — The key check runs before any handler
    pass      tests/unit/test_api.py::test_the_key_check_runs_before_any_handler · 1 runs
  TC-SVC-02.1  pass · 1 automated tests · verifies DSN-SVC-02 — A restart keeps every field of a record
    pass      tests/integration/test_store.py::test_a_restart_keeps_every_field · 1 runs

result: 5 matched automated tests · 5 matched runs · 0 unmatched run identities · exit 0 (informational) — report commit NOT VERIFIED; this repo's tests only

From a TRX file

The fixture project's C# agent runs the same test cases from xUnit. In this TRX file one [Fact] was skipped and one row of a [Theory] failed; each run is shown by its testName, with its outcome and the first line of its message:

report: report.trx
  3 XML entries · 3 reported runs (distinct full identities)
  matched: 3 runs of 2 automated tests · scanned: 2 automated tests · unmatched: 0 run identities
  matched against the current working tree — report commit NOT VERIFIED
  a partial parameter set does not prove every possible variant ran
  baselines: judged from reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines: no matching reachable local tag — nothing frozen locally
  change requests: ../ledger/change-requests (1 readable; 0 malformed) — current working tree, not pinned

requirements — verdicts along verifies links, from automated tests directly or through test cases:
  REQ-SVC-01  skip      via TC-SVC-01.1 · 1 automated tests · 1 runs — A call carries a key · requirement, in sibling ledger — not pinned · ../ledger/docs/req/service-srs.md:5
    via TC-SVC-01.1  skip · 1 automated tests · verifies REQ-SVC-01 — A call without a valid key is refused
      skip      tests/Agent.Tests/Unit/KeyCheckTests.cs::KeyCheckTests::Admits_NoKey_IsFalse · 1 runs
        skip: TC-SVC-01.1 a call without a key is refused (NotExecuted)
          NotExecuted: the key store is offline

test cases that reach no requirement — no requirement verdict inferred:
  TC-SVC-01.2  fail · 1 automated tests · verifies DSN-SVC-01 — The key check runs before any handler
    fail      tests/Agent.Tests/Unit/KeyCheckTests.cs::KeyCheckTests::Admits_AnyKey_DecidesAlone · 2 runs
      fail: TC-SVC-01.2 the key check decides before any handler(key: "a-wrong-key", admitted: True) (Failed)
        Failed: Expected KeyCheck.Admits(key, "the-key") to be True, but found False.

result: 2 matched automated tests · 3 matched runs · 0 unmatched run identities · exit 0 (informational) — report commit NOT VERIFIED; this repo's tests only

Repository boundary

Local tests can verify a sibling's requirement. The output labels its owner and the unpinned working-tree source; it does not claim to include the sibling's own tests:

report: report.xml
  1 XML entries · 1 reported runs (distinct full identities)
  matched: 1 runs of 1 automated tests · scanned: 2 automated tests · unmatched: 0 run identities
  matched against the current working tree — report commit NOT VERIFIED
  a partial parameter set does not prove every possible variant ran
  baselines: judged from reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines: no matching reachable local tag — nothing frozen locally
  change requests: NOT VERIFIED — ../ledger/change-requests is unavailable; fresh citations are verified at the ledger's import

requirements — direct verifies links only:
  REQ-CLT-01  no-result 1 automated tests · 0 runs — The client sends its key on every call · requirement · docs/req/client-srs.md:3
    no-result tests/unit/test_api.py::test_every_call_carries_the_key · 0 runs
  REQ-SVC-01  pass      1 automated tests · 1 runs — A call carries a key · requirement, in sibling service — not pinned · ../service/docs/req/service-srs.md:12

result: 1 matched automated tests · 1 matched runs · 0 unmatched run identities · exit 0 (informational) — report commit NOT VERIFIED; this repo's tests only

When the sibling cannot be read, a cited ID has an unknown type. Its linked test results are shown separately and are never presented as requirement verdicts:

report: report.xml
  1 XML entries · 1 reported runs (distinct full identities)
  matched: 1 runs of 1 automated tests · scanned: 2 automated tests · unmatched: 0 run identities
  matched against the current working tree — report commit NOT VERIFIED
  a partial parameter set does not prove every possible variant ran
  external AGR-*: NOT VERIFIED — ../ledger/agreement.md is not reachable; each cited AGR-N is judged at the ledger's import
  sibling service: NOT REACHABLE at ../service
  baselines: judged from reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines: no matching reachable local tag — nothing frozen locally
  change requests: NOT VERIFIED — ../ledger/change-requests is unavailable; fresh citations are verified at the ledger's import

requirements — direct verifies links only:
  REQ-CLT-01  no-result 1 automated tests · 0 runs — The client sends its key on every call · requirement · docs/req/client-srs.md:3
    no-result tests/unit/test_api.py::test_every_call_carries_the_key · 0 runs

unverified targets — type unknown, not requirement verdicts:
  REQ-SVC-01  pass      1 automated tests · 1 runs — REQ-SVC-01 · not verified here — judged at the ledger's import

result: 1 matched automated tests · 1 matched runs · 0 unmatched run identities · exit 0 (informational) — report commit NOT VERIFIED; this repo's tests only

Unread sources and graph violations remain visible. Matching uses the current working tree; qmstrace does not verify which commit produced a report. Results are not persisted.

Exit codes

  • 0: at least one scanned test matched and the informational view was produced. Failed tests, partial matches and graph findings do not change this code.
  • 2: usage or configuration prevented reading, or the report was unreadable, malformed, unsafe, empty, unsupported, or matched no scanned tests. The diagnostic suggests a next step.
  • 3: an internal fault.

Use the test runner's exit code — pytest's, or dotnet test's — to gate test success and check to gate traceability. See Generate and interpret a pytest report and Trace a C# repo for the workflows.