Output channels and authority
pytest-receptor uses three channels deliberately. They are complementary;
none is a hidden fallback for a different channel.
Process exit status
Pytest’s process exit status is the authority for automation. The receptor never changes it, including when it refines the human-readable label or when its own renderer fails.
Examples of label refinement are COLLECTION_ERROR exit=2 versus
INTERRUPTED exit=2, and USAGE_ERROR exit=5 | invalid selection when xdist
uses its no-tests status for explicit targets that do not exist. The number is
still pytest’s original status.
Standard output
Stdout carries the final receptor report. The first line of the receptor-owned block is the verdict, exit status, and counts. The block is plain text, deterministic for the same evidence, stripped of ANSI/control characters, and sanitized before rendering.
The whole stdout stream is not exclusively owned by the receptor. A compatible third-party plugin may publish its own terminal summary, and a process writing directly to file descriptor 1 can bypass pytest’s terminal writer. The receptor silences pytest’s presentation without unregistering that reporter or silencing other plugins.
Test-produced stdout is evidence, not control input. When relevant to a failure
it appears inside an explicitly labelled captured stdout section.
Standard error
Stderr carries bounded liveness progress after the twenty-second warm-up. It never carries the receptor’s final verdict. Pytest, native code, or another plugin may also write exceptional diagnostics there.
Discarding stderr leaves the receptor report parseable, but intentionally loses the live progress signal and may lose diagnostics owned by pytest or another plugin.
On-disk full report
When pytest’s cache provider is available, the full plain-text report is
published at session finish under the path printed by the receptor, normally
.pytest_cache/d/receptor/last-run.txt.
A previous report is removed at session start, so absence means “not yet”.
Publication happens once, after the complete report has been rendered.
The file is owner-only and a symlink is never followed.
The same sanitization and redaction used for stdout is applied before writing.
If the report cannot be written, compact output holds nothing back that would otherwise be recoverable only from that file.
-p no:cacheproviderdisables the report explicitly.
This file is the complete presentation artifact. It is separate from the
opt-in, versioned JSONL evidence stream produced by --receptor-events; see
Versioned evidence artifacts.
Versioned JSONL artifact
When explicitly requested, JSONL is streamed to the supplied path as normalized
events arrive. A final session_finish record and its integrity metadata make a
completed stream distinguishable from partial evidence left by an interrupted
process. The supported Python reader validates that distinction. This artifact
is the machine-oriented receptor evidence channel; pytest’s process status
remains the authority for the process that produced it.
Independent machine evidence
JUnit XML remains independent pytest-owned evidence when requested with
--junitxml. Compact reporting and the receptor artifact must not suppress or
mutate it. Keeping both is useful for parity audits and third-party tooling.
In short:
Need |
Authority |
|---|---|
Did the process succeed? |
pytest process exit status |
What should an agent read first? |
receptor block on stdout |
Is a long run still advancing? |
receptor progress on stderr |
What compact detail was omitted? |
on-disk full report |
What normalized receptor evidence should a tool read? |
versioned JSONL artifact |
What independent machine evidence can CI compare? |
pytest JUnit XML |