Skip to content

Trace Recording

Automatically capture the trace events your test process emits to .trz files, with configurable scopes and HTML report integration. Data that other producers send to the agent is not in the file.

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.