Skip to content

Trace Recording

Automatically capture all test data to .trz files with configurable scopes and HTML report integration.

Quick Start

# Record each test to its own file (artifacts dir required)
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts

# Record entire session to one file
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts --zelos-trace-file-scope=session

Recording does not need an agent. The plugin writes every trace event the test process emits to the file.

Recording Scopes

Control granularity of trace files:

Scope Description Use Case
function One file per test (default) Debugging individual tests
class One file per test class Related test groups
module One file per .py file Module-level analysis
session One file for entire run Full session replay

At class scope, a test outside a class gets its own file.

For a test TestMotor::test_start in tests/test_motor.py, each scope writes:

# Examples
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts --zelos-trace-file-scope=function  # 20240115-143022-zelos-trace-tests-test_motor-TestMotor-test_start.trz
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts --zelos-trace-file-scope=class     # 20240115-143022-zelos-trace-tests-test_motor-TestMotor.trz
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts --zelos-trace-file-scope=module    # 20240115-143022-zelos-trace-tests-test_motor.trz
pytest --zelos-trace-file --zelos-local-artifacts-dir=./artifacts --zelos-trace-file-scope=session   # 20240115-143022-zelos-trace.trz

File Naming

Default Naming

Files are named automatically using your artifact basename plus a sanitized test identifier:

{artifact_basename}-trace-{sanitized_nodeid}.trz

Examples:
20240115-143022-zelos-trace-tests-test_motor-TestMotor-test_start.trz
20240115-143022-zelos-trace-tests-test_motor-test_free.trz
20240115-143022-zelos-trace-tests-test_battery-test_charge[1].trz
  • artifact_basename comes from --zelos-artifact-basename (default is {date:%Y%m%d-%H%M%S}-zelos).
  • sanitized_nodeid is pytest's nodeid with .py removed, / and :: turned into -, and characters that are unsafe in file names removed. Parametrize brackets stay.
  • A session-scope file has no node id: {artifact_basename}-trace.trz.
  • If a filename already exists, a numeric suffix is added: .trz, .1.trz, .2.trz, ...

Custom Naming

Implement the hook in conftest.py. Return the name without the .trz extension, or None to keep the default:

from datetime import datetime


def pytest_zelos_trace_file_name(request):
    """Customize trace file names."""
    timestamp = datetime.now().strftime("%H%M%S")
    return f"trace_{request.node.name}_{timestamp}"

Return a name without dots. The plugin adds the .trz extension, and anything after a dot in the name can be replaced by it.

See Parameterized Tests for a variant that folds test parameters into the name.

HTML Report Integration

Trace files are automatically linked in HTML reports (requires pytest-html):

pytest --zelos-trace-file \
       --zelos-local-artifacts-dir=./artifacts \
       --html=artifacts/report.html

The report includes clickable links to trace files for each test.

  • Links are added only for the scopes relevant to each test (session/module/class/function) and require pytest-html.
  • Links use file:// URLs pointing to your local filesystem. If you open the report on another machine or CI artifact viewer, make sure the .trz files are available at the same paths.
  • If pytest-html is installed and --zelos-local-artifacts-dir is set, a self-contained report is auto-generated at {artifact_basename}-report.html in that directory without needing --html.

Streaming + Recording

Stream live while recording for later analysis:

pytest --zelos-trace --zelos-trace-url=grpc://agent:2300 \
       --zelos-trace-file --zelos-local-artifacts-dir=./artifacts

--zelos-trace streams to the agent; --zelos-trace-file records the same data to disk.

Directory Structure

Organized output:

artifacts/
├── 20240115-143022-zelos-trace-tests-test_motor-test_motor_start.trz
├── 20240115-143022-zelos-trace-tests-test_motor-test_motor_stop.trz
├── 20240115-143022-zelos-trace-tests-test_battery-test_battery_charge.trz
├── test_motor_start.checks.json          # check results, for tests that request `check`
└── 20240115-143022-zelos-report.html     # Links to all .trz files

Every file shares one timestamp: the plugin formats the basename once, when the run starts.

Configuration

pytest.ini

[pytest]
# Always record tests
addopts = --zelos-trace-file
          --zelos-local-artifacts-dir=./test-results
          --zelos-trace-file-scope=function
          --zelos-artifact-basename={date:%Y%m%d-%H%M%S}-test
  • --zelos-local-artifacts-dir is required when --zelos-trace-file is used. It resolves against pytest's rootdir, and the plugin creates it if absent.
  • --zelos-artifact-basename is a Python format string with one field, date: the run's start time as a datetime. The default includes a timestamp.

Advanced Patterns

Parameterized Tests: Include Parameters in Filenames

Add parameters to filenames using the hook:

# conftest.py
def pytest_zelos_trace_file_name(request):
    name = request.node.name
    if hasattr(request.node, "callspec"):
        params = request.node.callspec.params
        parts = [f"{k}={v}".replace(".", "_") for k, v in params.items()]
        name = f"{name}_{'_'.join(parts)}"
    return name

Troubleshooting

  • "Local artifacts directory is not set": pass --zelos-local-artifacts-dir=./artifacts (or set in pytest.ini).
  • No links in HTML report: ensure pytest-html is installed and you are generating an HTML report (e.g., --html=artifacts/report.html).
  • Missing .trz files on CI: the HTML links reference local paths; upload the .trz files as CI artifacts along with the report.