pytest-reportlog

A pytest plugin that streams test session events to a JSON Lines file for real-time monitoring and processing.

Tool
PyPI
v1.0.0
104stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
62/100Good
Development Activity60
Maintenance36
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture78
Code Quality80
Innovation80
Learning Curve70

pytest-reportlog is a small, focused pytest plugin that replaces the deprecated --resultlog option. When you run pytest with --report-log=FILE, it writes one self-contained JSON object per line for every collection event, test report, warning, and session start/finish event — following the JSON Lines convention so the file can be tailed and processed as the suite runs rather than parsed only after it completes.

Each JSON object carries a $report_type discriminator key so downstream consumers can safely skip report kinds they don’t recognize, which keeps the format forward-compatible as pytest itself evolves. The plugin also transparently compresses output based on file suffix (.gz, .bz2, .xz), and supports excluding captured logs from passing tests to keep large log files manageable.

What You Get

  • A --report-log=FILE CLI flag that writes JSON Lines output flushed after every event, so files can be tailed live
  • Automatic compression support for .gz, .bz2, and .xz output file suffixes with no extra configuration
  • A --report-log-exclude-logs-on-passed-tests flag to drop captured setup/call/teardown log sections for passing tests and keep files smaller
  • Forward-compatible event objects tagged with a $report_type key (SessionStart, SessionFinish, TestReport, CollectReport, WarningMessage) so unknown future fields or types don’t break existing consumers
  • Support for record_property output and pytest-xdist parallel test runs out of the box

Common Use Cases

  • Streaming test results into a CI dashboard or log aggregator in real time as a suite executes
  • Building custom test reporting or analytics tooling on top of a stable, documented JSON schema instead of scraping pytest’s terminal output
  • Archiving compressed, line-delimited test history for long-running or scheduled test suites
  • Feeding structured test events into log pipelines (e.g. via tail -f) for live monitoring of long test runs

Under The Hood

Architecture The entire plugin lives in one module, src/pytest_reportlog/plugin.py, registered with pytest through the pytest11 entry point declared in pyproject.toml. pytest_configure instantiates a single ReportLogPlugin and registers it with pytest’s plugin manager, explicitly skipping registration on pytest-xdist worker processes (checked via hasattr(config, "workerinput")) so only the controller process writes the log file. The plugin implements a small set of pytest hook callbacks — pytest_sessionstart, pytest_sessionfinish, pytest_runtest_logreport, pytest_warning_recorded, pytest_collectreport, and pytest_terminal_summary — all funneling through one _write_json_data method, which keeps serialization and file-writing logic centralized. Report objects themselves are serialized by delegating to pytest’s own pytest_report_to_serializable hook rather than reimplementing that logic, including a small compatibility shim (lines 93-95) that normalizes a _report_type key emitted by the third-party subtests plugin into the expected $report_type. Because nearly every consumer downstream depends on this implicit JSON schema, any change to the hook-to-JSON mapping is effectively a breaking change to the file format.

Tech Stack The project is pure Python, packaged with hatchling and hatch-vcs for git-tag-derived versioning, and declares a single runtime dependency on pytest itself (unpinned, relying on pytest’s own hook compatibility). Development dependencies are limited to pre-commit and tox for linting and cross-version test matrices. There is no database, web framework, or network layer — it’s a filesystem-writing plugin only. GitHub Actions (test.yml, deploy.yml) handle CI and PyPI publishing, with Dependabot configured for automated dependency PRs; the badges in the README also indicate the package is mirrored to conda-forge.

Code Quality Tests in tests/test_reportlog.py use pytest’s own testdir/pytester fixtures to spawn sub-processes running real pytest suites and assert on the resulting JSON Lines output, including a parametrized test (test_open_filtered) that exercises all four supported compression codecs, and a targeted regression test (test_subtest) guarding a specific fixed bug (_report_type normalization for the subtests plugin). Some functions carry type hints (Dict[str, Any], TextIO, a typed Protocol for the compression opener), though the project does not run mypy in CI. Error handling is intentionally minimal — a single try/except TypeError fallback that stringifies unserializable values rather than failing the whole write. Style is enforced via pre-commit (black) and CI runs the suite across multiple Python versions.

API Design The plugin’s entire public surface is one CLI flag, --report-log=FILE, plus one opt-out flag for log verbosity — there is no Python API to learn, no configuration file, and no setup beyond installing the package. Compression is inferred automatically from the output filename’s suffix, and the JSON schema is documented directly in the README with a full worked example (input test file, terminal output, and resulting JSON Lines), making the format easy to consume from any language without reading source code.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search