Pytest¶
Logfire includes a built-in pytest plugin that enables distributed tracing for your test suite. The plugin creates spans for test sessions and individual tests, allowing you to see exactly what happens during test execution.
Installation¶
The pytest plugin is included with logfire - no additional installation required:
pip install logfire
uv add logfire
conda install -c conda-forge logfire
Enabling the Plugin¶
The plugin can be enabled in several ways:
Command Line Flag¶
pytest --logfire
Configuration File¶
[pytest]
logfire = true
[tool.pytest]
logfire = true
Auto-Enable in CI¶
The plugin automatically enables when both:
CIenvironment variable is set to a non-empty stringLOGFIRE_TOKENenvironment variable is present
This means your CI pipelines will automatically get tracing without any configuration changes.
Explicitly Disable¶
To explicitly disable the plugin (useful to override auto-enable in CI):
pytest --no-logfire
Configuration Options¶
| Option | CLI Flag | Config option | Environment variable | Default | Description |
|---|---|---|---|---|---|
| Enable | --logfire |
logfire = true |
- | false |
Enable the plugin |
| Disable | --no-logfire |
- | - | - | Explicitly disable |
| Service Name | --logfire-service-name |
logfire_service_name |
LOGFIRE_SERVICE_NAME |
pytest |
Service name for traces |
Configuration priority: CLI > Environment Variable > INI > Default
Trace Hierarchy¶
When running tests with --logfire, the plugin creates a hierarchical trace structure:
pytest: {project-name} (session span)
├── test_module.py::test_one (test span)
│ └── custom span (your spans)
├── test_module.py::test_two (test span)
└── test_module.py::TestClass::test_three (test span)
Session Span¶
The session span (pytest: {project-name}) wraps the entire test run and includes:
| Attribute | Description |
|---|---|
pytest.args |
Command line arguments |
pytest.rootpath |
Project root path |
pytest.startpath |
Invocation path |
pytest.testscollected |
Number of tests collected |
pytest.testsfailed |
Number of tests failed |
pytest.exitstatus |
Exit code |
Test Spans¶
Each test gets its own span with:
| Attribute | Description |
|---|---|
test.name |
Test function name |
test.nodeid |
Full pytest node ID (e.g., test_file.py::test_func) |
test.class |
Test class name (if applicable) |
test.module |
Test module name |
test.parameters |
Parameterized test arguments (JSON) |
test.outcome |
passed, failed, or skipped |
test.duration_ms |
Test duration in milliseconds |
code.filepath |
Path to test file |
code.function |
Test function name |
code.lineno |
Line number |
Using with Instrumented Libraries¶
When running tests with --logfire, any instrumented library calls create spans nested under the test span. This provides end-to-end visibility into what your tests are doing.
Example: Custom Spans in Tests¶
import logfire
def test_user_workflow():
"""Test a complete user workflow."""
with logfire.span('create user'):
# Simulate user creation
user = {'id': 123, 'name': 'Test User'}
assert user['name'] == 'Test User'
with logfire.span('verify user'):
# Verify the user was created correctly
assert user['id'] == 123
Running with pytest --logfire produces this trace hierarchy:
pytest: my-project
└── test_api.py::test_user_workflow
├── create user
└── verify user
Example: Logging During Tests¶
import logfire
def test_operation():
logfire.info("Starting operation")
result = perform_operation()
logfire.info("Operation completed", result=result)
assert result == expected
All log messages appear as spans nested under the test span.
Linking to External Traces¶
You can link your test traces to external systems using the TRACEPARENT environment variable:
TRACEPARENT="00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" pytest --logfire
This follows the W3C Trace Context specification, allowing your test runs to be part of a larger distributed trace.
Benefits¶
- Debugging Failed Tests: See exactly what operations occurred before a test failure
- Performance Analysis: Identify slow operations within your tests
- Integration Testing: Verify that your code makes the expected calls to external services
- CI Visibility: Get detailed traces from your CI pipelines automatically
Example: Viewing in Logfire¶
After running your tests with --logfire, you can view the traces in the Logfire web UI:
- Navigate to your project in Logfire
- Filter by service name
pytest(or your custom service name) - Explore the trace hierarchy to see:
- Which tests passed/failed
- How long each test took
- What operations occurred within each test
- Any exceptions that were raised
Migration from conftest.py Pattern¶
If you were previously using a manual tracing pattern in conftest.py:
# Old pattern - no longer needed
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
with logfire.span("test: {test_name}", test_name=item.name):
yield
You can remove this code and simply use pytest --logfire instead. The built-in plugin handles all the tracing automatically with more comprehensive attributes.