Reference

Test Record JSON Format

Field-by-field reference for the JSON file OpenHTF's OutputToJSON writes — top-level record, metadata, phases, measurements, validators, units, attachments, subtests, branches, checkpoints, diagnoses, log records — with a complete annotated sample.

Last updated · Verified with OpenHTF 1.6.1

json_factory.OutputToJSON serializes the in-memory TestRecord with the fields below (key order in the file: dut_id, timestamps, outcome, outcome_details, marginal, metadata, phases, subtests, branches, diagnosers, diagnoses, log_records, station_id, code_info). Checkpoint evaluations are kept in memory (TestRecord.checkpoints) but are not written to JSON in 1.6.1. The format has been stable since 1.5; 1.6 added nothing incompatible. Timestamps are milliseconds since the Unix epoch, enums are their string names.

Top level

dut_idstring
Serial number or identifier of the unit. UNKNOWN_DUT if never set.
station_idstring
From configuration; defaults to the hostname.
start_time_millis / end_time_millisint
Wall-clock bounds of the run.
outcomePASS | FAIL | ERROR | TIMEOUT | ABORTED
Overall result. Test outcomes →
outcome_detailsarray
{code, description} entries explaining a non-PASS outcome — the exception type and message for ERROR, the failing phase for FAIL.
marginalbool | null
true if any measurement was marginal.
metadataobject
test_name, config (the loaded configuration) and every keyword passed to htf.Test(). Metadata →
code_infoobject
{name, docstring, sourcecode} of the test module. sourcecode is empty unless capture_source is on.
phasesarray
One phase record per executed phase attempt, in order. The start trigger (prompt_for_test_start() or a lambda) is recorded first as trigger_phase; phases skipped by run_if are absent.
subtestsarray
{name, outcome: PASS|FAIL|STOP, start_time_millis, end_time_millis, marginal} per subtest.
branchesarray
Per BranchSequence: {name, diag_condition, branch_taken, evaluated_millis}.
diagnosersarray
Test-level diagnosers that ran.
diagnosesarray
Every Diagnosis: {result, description, component, priority, is_failure}.
log_recordsarray
{level, logger_name, source, lineno, timestamp_millis, message}. level is the Python logging number (20 = INFO).

Phases

namestring
Function name, or PhaseOptions.name after template substitution.
outcomePASS | FAIL | SKIP | ERROR
Per-phase result. SKIP for PhaseResult.SKIP and for repeated attempts under the limit.
resultobject
{phase_result: CONTINUE|STOP|REPEAT|SKIP|FAIL_AND_CONTINUE|FAIL_SUBTEST}, or {phase_result: null, raised_exception: {...}} on error.
marginalbool
Any marginal measurement in this phase.
start_time_millis / end_time_millisint
measurementsobject
Keyed by measurement name — see below.
attachmentsobject
Keyed by attachment name: {mimetype, sha1} plus data (base64) when inline_attachments=True. Attachments →
optionsobject
The PhaseOptions in effect: timeout_s, repeat_limit, run_if (as a string), requires_state, force_repeat, repeat_on_timeout, repeat_on_measurement_fail, run_under_pdb, phase_name_case, stop_on_measurement_fail.
diagnosers / diagnosis_results / failure_diagnosis_resultsarray
Phase-level diagnosers and the diagnosis result names they produced.
subtest_namestring | null
Set when the phase ran inside a subtest.
codeinfoobject
{name, docstring, sourcecode} of the phase function.
descriptor_idint
Internal identity of the phase descriptor; identical across repeats of the same phase.

Measurements

namestring
outcomePASS | FAIL | UNSET | PARTIALLY_SET
UNSET when declared but never assigned (fails the phase unless allow_unset_measurements). PARTIALLY_SET for dimensioned measurements with some coordinates missing.
measured_valuenumber | string | bool | array
Scalar, or for dimensioned measurements an array of rows [dim1, dim2, ..., value].
validatorsarray of string
str() of each validator, e.g. "3.2 <= x <= 3.4", "'x' matches /^1\\.4/". Validators →
unitsobject
{name, code, suffix} from openhtf.util.units; absent if no unit.
dimensionsarray
One {name, code, suffix} (or description) per axis of a multi-dimensional measurement.
docstringstring
From .doc().
marginalbool
set_time_millisint
When the value was set.

Annotated sample

A two-phase functional test, trimmed to the essentials:

SN-0001.functional_test.json
{
  "dut_id": "SN-0001",
  "station_id": "station-a",
  "start_time_millis": 1737000000000,
  "end_time_millis": 1737000012500,
  "outcome": "PASS",
  "outcome_details": [],
  "marginal": false,
  "metadata": {
    "test_name": "TP-DEMO-1 Functional Test",
    "config": {
      "station_id": "station-a",
      "stop_on_first_failure": false,
      "allow_unset_measurements": false,
      "capture_source": false
    }
  },
  "code_info": { "name": "main", "docstring": null, "sourcecode": "" },
  "phases": [
    {
      "name": "power_on",
      "outcome": "PASS",
      "result": { "phase_result": "CONTINUE" },
      "marginal": false,
      "start_time_millis": 1737000000200,
      "end_time_millis": 1737000004000,
      "measurements": {
        "supply_voltage": {
          "name": "supply_voltage",
          "outcome": "PASS",
          "validators": ["3.2 <= x <= 3.4"],
          "units": { "name": "volt", "code": "VLT", "suffix": "V" },
          "measured_value": 3.31
        },
        "boot_ok": {
          "name": "boot_ok",
          "outcome": "PASS",
          "validators": ["'x' is equal to 'True'"],
          "measured_value": true
        }
      },
      "attachments": {},
      "options": { "timeout_s": null, "repeat_limit": null, "phase_name_case": "KEEP" },
      "subtest_name": null,
      "codeinfo": { "name": "power_on", "docstring": null, "sourcecode": "" }
    },
    {
      "name": "rf_check",
      "outcome": "PASS",
      "result": { "phase_result": "CONTINUE" },
      "measurements": {
        "tx_power_dbm": {
          "name": "tx_power_dbm",
          "outcome": "PASS",
          "validators": ["17.0 <= x <= 20.0"],
          "units": { "name": "Decibel-milliwatts", "code": "DBM", "suffix": "dBm" },
          "measured_value": 18.7
        },
        "firmware_version": {
          "name": "firmware_version",
          "outcome": "PASS",
          "validators": ["'x' matches /^1\\.4\\.2$/"],
          "measured_value": "1.4.2"
        }
      }
    }
  ],
  "subtests": [],
  "branches": [],
  "diagnosers": [],
  "diagnoses": [],
  "log_records": [
    {
      "level": 20,
      "logger_name": "openhtf.test_record.<uid>.phase.power_on",
      "source": "main.py",
      "lineno": 18,
      "timestamp_millis": 1737000000210,
      "message": "Rail up"
    }
  ]
}

Parsing tips

  • Iterate phases[], then measurements values; do not assume measurement names are unique across phases.
  • A multi-dimensional measured_value is a list of rows; the last element of each row is the value, the preceding ones are the coordinates in dimensions order.
  • outcome_details[0].description holds the traceback summary for ERROR runs.
  • Repeated phases appear as several entries sharing descriptor_id and name; only the last has the final outcome.
  • File size is dominated by attachments[].data when inlined; write attachments elsewhere with inline_attachments=False if you index the JSON.

TofuPilot's import and upload() callback read this exact format — phases, measurements with limits and units, attachments and logs — see Manufacturing Test Analytics.

On this page

First-pass yield
0%4.1
Track with TofuPilot