API Reference — pytest Plugin¶
RAMPART's pytest integration. Activates automatically when installed.
_collection
¶
Result collection infrastructure for the pytest plugin.
Provides the ContextVar-based mechanism for collecting Result objects produced during test execution. The pytest plugin activates a collector per test; execution event handlers write into it automatically.
ResultCollectionHandler
¶
Bases: ExecutionEventHandler
Default ExecutionEventHandler installed on every BaseExecution.
Writes the Result into the active per-test collector on ON_POST_EXECUTE. No-op for all other events. No-op when no collector is active (safe to use outside pytest).
on_event_async
async
¶
Record result on post-execute. Ignore all other events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_data
|
ExecutionEventData
|
The event data. |
required |
Source code in rampart/pytest_plugin/_collection.py
ResultCollector
¶
record_result
¶
Record a Result into the active test's collector.
For building-block tests that construct Results manually rather than via Attacks. or Probes. factories. No-op when called outside a pytest test context (e.g., in library usage or scripts).
Re-exported from rampart at the top level — consumers import it as:
from rampart import record_result
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
Result
|
The result to record. |
required |
Source code in rampart/pytest_plugin/_collection.py
_session
¶
Session-scoped state for the RAMPART pytest plugin.
Accumulates Result objects, computes trial group aggregates, and builds the final TestRunReport.
RampartSession
¶
Session-scoped state for the RAMPART plugin.
Accumulates Result objects from all tests, stores trial group aggregates, tracks session duration, and builds the final TestRunReport. Holds configured sinks for report emission.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sinks
|
list[ReportSink]
|
Report sinks to emit to at session end. Defaults to an empty list (terminal-only output). |
None
|
Source code in rampart/pytest_plugin/_session.py
results_by_nodeid
property
¶
Read-only view of results grouped by pytest node ID.
is_emitted
property
¶
True once report emission has been attempted (idempotency guard).
incomplete_reasons
property
¶
The recorded reasons the run is incomplete (empty if complete).
trial_specs
property
¶
Read-only view of registered trial specs, keyed by clone node ID.
add_sinks
¶
Register additional sinks for report emission.
Called by the fixture-based bootstrap to add team-provided sinks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sinks
|
list[ReportSink]
|
Sinks to append. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If any item does not satisfy ReportSink. |
Source code in rampart/pytest_plugin/_session.py
set_duration
¶
Set the total session duration.
Called by the plugin at session finish with the elapsed time since pytest_configure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duration_seconds
|
float
|
Total wall-clock seconds. |
required |
Source code in rampart/pytest_plugin/_session.py
| Python | |
|---|---|
absorb
¶
Absorb results from a completed test's collector.
Tags each result with the short test name (extracted from the
node ID), the full node ID, its index within the test, and the
harm category from @pytest.mark.harm. The nodeid and index
give a total, deterministic ordering for the terminal summary and
report regardless of xdist worker completion order.
Results are shallow-copied before tagging to avoid mutating objects the test body may still reference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
Item
|
The test item that just completed. |
required |
collector
|
ResultCollector
|
The test's result collector. |
required |
Source code in rampart/pytest_plugin/_session.py
record_trial_group
¶
Record aggregate statistics for a trial group.
Semantics:
- Any UNSAFE result across all trials -> group FAILS
- threshold is the minimum pass rate (SAFE / total).
e.g. 0.8 means at least 80% of runs must be SAFE.
- ERROR results count against the pass rate (they're not SAFE).
- Clones with zero results (skipped or crashed before producing
a Result) are tracked as no_result and count against
the pass rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_nodeid
|
str
|
The original test's node ID. |
required |
clone_nodeids
|
Sequence[str]
|
Pytest node IDs of all clones in this trial group. |
required |
threshold
|
float
|
Minimum pass rate required. |
required |
Source code in rampart/pytest_plugin/_session.py
register_trial_spec
¶
Record trial metadata for a cloned item at collection time.
Called from pytest_collection_modifyitems whenever a
@pytest.mark.trial test is expanded into clones. Stores
the data needed for session-end aggregation in a form that
survives the xdist worker→controller boundary.
Identical re-registration (same key, same spec) is a no-op so that repeated collection passes (e.g., in workers and the controller) converge safely.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clone_nodeid
|
str
|
Node ID of the cloned item. |
required |
base_nodeid
|
str
|
Node ID of the original (uncloned) item. |
required |
threshold
|
float
|
Pass-rate threshold from the trial marker. |
required |
Source code in rampart/pytest_plugin/_session.py
merge_trial_specs
¶
Merge trial specs received from an xdist worker payload.
Idempotent: re-merging identical specs is a no-op. Spec values from workers should match the controller's own collection because the same plugin code runs in every process; we merge defensively so the controller can aggregate correctly even when its own collection state is unavailable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial_specs
|
Mapping[str, TrialSpec]
|
Specs keyed by clone node ID. |
required |
Source code in rampart/pytest_plugin/_session.py
merge_worker_results
¶
Merge an xdist worker's results into this session.
Extends both the flat _results list and the
_results_by_nodeid mapping. Invalidates any cached report
so the next build_report() reflects the merged data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
results_by_nodeid
|
dict[str, list[Result]]
|
Worker results grouped by pytest node ID. |
required |
Source code in rampart/pytest_plugin/_session.py
mark_emitted
¶
mark_incomplete
¶
Record that a worker failed to deliver complete results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reason
|
str
|
A short human-readable explanation surfaced in the report metadata. |
required |
Source code in rampart/pytest_plugin/_session.py
set_report_metadata
¶
Attach run-level metadata that will appear on TestRunReport.
Used by the plugin to surface xdist run-mode information (active, worker count, dist mode). Subsequent calls merge into existing metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
dict[str, object]
|
Key/value pairs to attach. |
required |
Source code in rampart/pytest_plugin/_session.py
build_report
¶
Build a TestRunReport from all collected results.
The report is cached and reused on subsequent calls. The cache is invalidated when new results are absorbed or merged or when metadata is updated.
Results are sorted by (_pytest_nodeid, _rampart_result_index,
_rampart_source_worker) for a total, deterministic ordering across
xdist worker completion orders. _pytest_nodeid falls back to
_pytest_test_name and _rampart_source_worker is absent
(constant) outside xdist, so single-process ordering is unaffected.
These leading-underscore keys are RAMPART scheduling bookkeeping, namespaced to avoid colliding with user-supplied result metadata.
Returns:
| Name | Type | Description |
|---|---|---|
TestRunReport |
TestRunReport
|
Aggregated test run results. |
Source code in rampart/pytest_plugin/_session.py
Parallel Execution Hooks¶
When pytest-xdist is installed, the plugin streams Result envelopes on call
reports, with a non-passing setup fallback when no call report will occur,
through pytest_runtest_logreport. It uses the optional pytest_testnodedown
hook to reconcile per-worker Result counts. See
Parallel Execution for the data flow and trust boundary.
_xdist
¶
xdist support for RAMPART's pytest plugin.
Provides serialization, deserialization, and controller-side merge
logic for running RAMPART under pytest-xdist. Workers stream Result
objects on call-phase test reports; the controller merges each report
incrementally and emits a single unified report at session end.
Trust boundary: worker payloads may contain attacker-controlled content (agent responses, payload text). Serialization is strictly JSON-safe primitives; deserialization validates schema version, enum values, and metadata depth; ANSI escapes are stripped from free text as defense-in-depth.
WorkerOutputError
¶
Bases: Exception
Base error for xdist worker output processing failures.
SchemaVersionError
¶
Bases: WorkerOutputError
Raised when a worker payload has missing or unknown schema version.
SizeLimitError
¶
Bases: WorkerOutputError
Raised when one serialized Result exceeds the configured size cap.
is_xdist_worker
¶
Return True when this process is a pytest-xdist worker.
Detection is attribute-based; no xdist import required, so this function is safe to call when pytest-xdist is not installed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
The pytest configuration object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if running in an xdist worker process. |
Source code in rampart/pytest_plugin/_xdist.py
is_xdist_controller
¶
Return True when this process is the pytest-xdist controller.
The controller is the non-worker process that owns an active
distribution: a --dist mode other than "no" plus at least one
way of spawning execution endpoints (--numprocesses workers or
explicit --tx gateways). Keying off distribution rather than the
worker count alone keeps -d/--tx runs (no -n) on the
controller path while excluding a bare --dist with no endpoints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
The pytest configuration object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if running in the xdist controller process. |
Source code in rampart/pytest_plugin/_xdist.py
get_dist_mode
¶
Return the active --dist mode string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
The pytest configuration object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The dist mode (e.g., |
Source code in rampart/pytest_plugin/_xdist.py
| Python | |
|---|---|
get_worker_count
¶
Return the number of xdist workers configured.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
The pytest configuration object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Number of workers (0 when xdist is not active). |
Source code in rampart/pytest_plugin/_xdist.py
attach_report_results
¶
Attach serialized Results to a call-phase worker report.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Number of Result representations attached. |
Source code in rampart/pytest_plugin/_xdist.py
serialize_report_data
¶
Serialize call-phase Results into an execnet-safe report envelope.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
dict[str, Any]: JSON-safe report envelope. |
Source code in rampart/pytest_plugin/_xdist.py
deserialize_report_data
¶
Deserialize one call-phase report envelope.
Performs strict schema validation: missing schema key, unknown
versions, and malformed enum values all raise WorkerOutputError
(or subclass). The report nodeid and envelope nodeid must agree.
Each result's metadata["_pytest_nodeid"] and
metadata["_rampart_result_index"] are set authoritatively from the
envelope nodeid and list position so cross-worker ordering is total
and independent of any (untrusted) serialized values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
object
|
The deserialized private TestReport attribute. |
required |
report_nodeid
|
str
|
The nodeid from the owning TestReport. |
required |
Returns:
| Type | Description |
|---|---|
tuple[dict[str, list[Result]], bool]
|
tuple[dict[str, list[Result]], bool]: Results grouped by nodeid and whether any Result is a truncation marker. |
Raises:
| Type | Description |
|---|---|
SchemaVersionError
|
Missing or unknown schema version. |
WorkerOutputError
|
Malformed payload (type errors, bad enums). |
Source code in rampart/pytest_plugin/_xdist.py
merge_report_results
¶
Validate and incrementally merge one streamed report envelope.
Returns:
| Type | Description |
|---|---|
tuple[str, int] | None
|
tuple[str, int] | None: Source worker and merged Result count, or None when the report carries no RAMPART envelope. |
Source code in rampart/pytest_plugin/_xdist.py
serialize_worker_data
¶
Serialize slim session-level worker data for the controller.
Results are deliberately absent because call-phase reports are the sole Result transport. Workeroutput retains trial specs and the expected streamed Result count for completeness reconciliation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
RampartSession
|
The worker's session state. |
required |
streamed_result_count
|
int
|
Result representations attached to reports by this worker. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
dict[str, Any]: A JSON-safe payload ready to write to
|
Source code in rampart/pytest_plugin/_xdist.py
deserialize_trial_specs
¶
Deserialize the trial_specs section of a worker payload.
Missing or malformed entries are skipped rather than raised so
that a partially-corrupt payload still merges results. The
trial_specs field is optional: payloads without trials emit
an empty list and this function returns an empty dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
object
|
The deserialized JSON object from
|
required |
Returns:
| Type | Description |
|---|---|
dict[str, TrialSpec]
|
dict[str, TrialSpec]: Trial specs keyed by clone node ID. |
Raises:
| Type | Description |
|---|---|
SchemaVersionError
|
Missing or unknown schema version. |
WorkerOutputError
|
|
Source code in rampart/pytest_plugin/_xdist.py
finalize_worker
¶
Serialize slim worker session state into config.workeroutput.
Called from pytest_sessionfinish on each xdist worker. The
worker skips sink emission entirely; the controller is responsible
for the final report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
The pytest configuration object. |
required |
session
|
RampartSession
|
The worker's session state. |
required |
streamed_result_count
|
int
|
Number of Result representations attached to test reports by this worker. |
required |
Source code in rampart/pytest_plugin/_xdist.py
handle_testnodedown
¶
Reconcile a finished worker's streamed Result count.
Called from pytest_testnodedown on the controller for each
worker that completes. Failures (missing payload, deserialization
errors, worker crashes) are recorded via mark_incomplete rather
than raised, so a single bad worker does not abort report emission.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
RampartSession
|
The controller's session state. |
required |
node
|
object
|
The xdist node object (has |
required |
error
|
object
|
The shutdown error from xdist, or None on clean exit. |
required |
received_result_count
|
int
|
Results already merged from this worker. |
required |
Source code in rampart/pytest_plugin/_xdist.py
| Python | |
|---|---|
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 | |