Repository navigation
Description
Summary
An editor shows mcpp test through mcpp test --message-format json and the run kept under target/mtest. mcpp-ide's test views (mcpp-ide#8: VS Code, CLion and Neovim) need four additions to these outputs:
- a case's result as it happens;
- a case's metrics and their bounds;
- the parts of a program of several files;
- the fields of the mtest store (spec P12) that a reader of a run uses.
mcpp already reads every one of these from a test program. It does not carry them into the records or the store.
Each addition is a field or record kind added to an existing output (the guarantees docs/50 applies to the test stream: fields are added, never removed). Each is announced by a feature that a client gates on.
Measured (mcpp 2026.11.9.1)
A project with [test] programs = "directory" and two files, tests/unit/a.cpp and tests/unit/b.cpp, each with one mtest case:
| Output | Names the program |
|---|---|
mcpp test --list --message-format json |
{"test":"unit","main":".../tests/unit/a.cpp"} |
mcpp test --cases --message-format json |
test: "unit", listed with each case's file and line |
mcpp test --message-format json |
two records, test: "unit/a" and test: "unit/b" (one process per file) |
target/mtest/runs/<id>/cases.ndjson |
{"program":"unit/a","id":"alpha","status":"pass","ms":…,"reason":"","failures":[]} |
The gaps:
- The parts are not stated. The list names
unit; the run reportsunit/aandunit/b. A client that lists the program cannot tell which records belong to it, or which file a part is, without reproducing the split rule.mainnames the first file of the directory, which a program of"directory"does not begin at when no file definesmain. - Results arrive per process.
src/build/test_protocol.cppmreadsMTEST_REPORTafter the process ends. The protocol writes the report as NDJSON appended event by event (P5.1), sobeginandendare on disk while the program runs. A program of many cases (a conformance or e2e program runs for minutes) shows nothing until it ends. - Metrics are dropped. The parser keeps
program,case,begin,failure,end,missinganddone. It ignoresmetric(P5.2, P6) andusage(P10.2), and thecaseevent'sbounds(P6.5). ABenchcase's measurements and the limits it states reach neither the record nor the store. - The store lacks fields P12 lists.
cases.ndjsonhas nokind,started_ms,metrics,boundsortags.failureshas noexpectedoractual, though the record carries them.programs.ndjsonhas nobuild_started_msorusage.mtest report|analyze|graph --store target/mtesttherefore have no kinds, no metrics, no trend and no case-level schedule for a run ofmcpp test.
Proposal
1. test-parts: the parts of a program
Under --list and --cases, the record of a program that runs as several processes gains parts:
{"test":"unit","main":null,"files":["tests/unit/a.cpp","tests/unit/b.cpp"],
"parts":[{"name":"unit/a","file":".../tests/unit/a.cpp"},{"name":"unit/b","file":".../tests/unit/b.cpp"}]}fileslists the program's own sources: for a program of"directory", every file of it.mainis the file that definesmain, ornullwhen none does.partsis how[test] splitdivides a run ("file": one per file;"none": absent;"case": absent, since a case's process is named by the case).- A run record of a part gains
part_of: "unit".
2. test-case-stream: case results as they happen
mcpp test --message-format json reads MTEST_REPORT while the program runs. For each begin and end it writes a record before the program's record:
{"case":{"member":"","test":"unit/a","id":"alpha","event":"begin","t_ms":12}}
{"case":{"member":"","test":"unit/a","id":"alpha","event":"end","status":"fail","ms":3.1,"reason":"",
"failures":[{"file":"tests/unit/a.cpp","line":3,"message":"…","expected":"1","actual":"2"}]}}t_mscounts from the start of the run, asstarted_msdoes in the store.- The program's record still follows with all its
cases, so a client that reads only program records is unchanged. - A program killed mid-run leaves its streamed records valid: a
beginwithout anendfails, as P5.4 states.
3. test-metrics: metrics and bounds
- A case in the record's
casesgains:metrics:[{"name","value","unit","samples"?,"better"?,"precision"?}];bounds:[{"metric","max"?,"min"?}];kindandtags, from the case'scaseevent or itsbegin(P3.4).
- The program's record gains
usage(P10.2). listedentries gainbounds.- The
endrecord oftest-case-streamcarries the same fields.
4. The store as P12 states it
cases.ndjsongainskind,tags,started_ms,metricsandbounds.failuresentries gainexpectedandactual.programs.ndjsongainsbuild_started_msandusage.mtest analyze trend --store target/mtestthen shows aBenchcase's metrics beside its bounds overmcpp test's runs.mtest graph --run last --store target/mtest --format ganttthen draws the schedule at case level.
Features
| feature | meaning | read by |
|---|---|---|
test-parts |
§1 | an IDE's test tree |
test-case-stream |
§2 | an IDE's live test results |
test-metrics |
§3 and §4 | an IDE's metrics, bounds and trends |
Consumer
mcpp-ide#8 implements the client side against these names and gates each view on its feature. With an older mcpp, the views are:
- the tree, from the part names;
- results per process;
- no metrics, with the reason in
capabilities/explain.
The fixtures of mcpp-ide's mock mcpp record the shapes above. A change of a name or field here is a change there.
Compatibility
Every change adds a field or a record kind:
- a
caserecord has one top-level key,case, beside the stream'stest,summary,group_buildandworkspace_summaryrecords, so a client that dispatches on the keys it knows skips it; - the store's added fields are P12's, which
mtestalready reads.
No existing field changes meaning.
Activity
2026.11.10.1: base packages, Windows GNU-ABI from every host, FreeBSD…
speak-agent commentedon Nov 10, 2026
Released in mcpp 2026.11.10.1 (#916):
test-parts,test-case-streamandtest-metricsas described here (e2e 1065). The same release states the runner's contract as the mcpp test spec,docs/specs/test.md(SPEC-017 v2.0). The spec has a base every framework implements (B1–B6) and optional capabilities a framework states of itself (O1–O9): launch records, framework declarations, per-case checks and output, and test sessions. mtest 0.6.0 implements the optional capabilities, and mcpp-ide 1.5.0 reads tests only through the spec.