Skip to content

Result Reporting

Loading -p f3ts reports every test automatically — no special code in your tests. This page explains how a pytest result becomes an F3TS result, and how f3ts_assert adds sub-results.

The automatic flow

  1. Registration. When pytest configures, the plugin registers a reporter (unless you pass --teardown).

  2. Per test. On each test's call phase the reporter builds a ResultCreate from the pytest report — test_name, start, stop, duration, passed.

  3. Enrichment via user_properties. The reporter doesn't get your config directly. Instead the autouse auto_logger fixture records it: record_property("test_config", test_config.model_dump()). pytest stores that on the report's user_properties, and the reporter reads it back and copies these fields onto the result:

    test_id, description, error_code, error_msg, min_limit, max_limit, meas

    The measured value meas is a local variable, so you record it yourself with log_vars(record_property) (see Fixtures).

  4. Send. The result goes to the active client — the backend (online) or the in-memory store (offline). See Online vs Offline.

  5. On failure. The reporter also sends an error notification built from error_code / error_msg.

  6. End of run. A run-level update (duration, pass/fail counts) is sent, and offline the summary table is printed.

f3ts_assert sub-results

f3ts_assert reports each assertion as its own result row — a sub-result — and then performs the real assertion. It keeps a counter and composes the sub-result's test_id as "<base>.<n>" (1, 2, …) under the test's test_id:

python
def test_power_rails(interface, f3ts_assert):
    for rail in ("5v0", "3v3", "1v8"):
        meas = interface.measure_rail(rail)
        f3ts_assert(assert_value=(meas > 0), meas=meas, description=f"{rail} present")

For a test whose test_id is 2.1, this emits sub-results 2.1.1, 2.1.2, 2.1.3. Each sub-result is sent (and, on failure, an error notification too) before the assertion runs, so a failing sub-result is recorded even though it then stops the test. Result fields you don't pass (min_limit, max_limit, description, test_id, …) are taken from the test's test_config.

What this means for you

Write ordinary pytest tests and you get reporting for free. Reach for log_vars to record a measurement, test_config for limits, and f3ts_assert when one test checks several things.