Test Record

Complete reference for the OpenHTF test record structure including test outcomes, phase records, measurement data, attachments, and diagnosis results.

Last updated · Verified with OpenHTF 1.6.1

Understand the complete test record that OpenHTF produces after every test execution.

The test record holds the device identifier, the test outcome, one record per phase with its measurements and attachments, the log records and the diagnoses produced during the test.

  • TestRecord
  • dut_id
  • outcome
  • phases[]
  • measurements
  • attachments
  • log_records[]
  • diagnoses[]

Every test execution produces a TestRecord — a structured object containing everything that happened: outcomes, measurements, phase results, logs, attachments, and diagnoses. Output callbacks receive this record to write JSON, send to a database, or integrate with systems like TofuPilot.

Test record structure

dut_idstr

Serial number or identifier of the device under test.

station_idstr

Identifier of the test station that ran the test.

outcomeOutcome

Overall test result: PASS, FAIL, ERROR, TIMEOUT, or ABORTED.

outcome_detailslist[OutcomeDetails]

Additional context for the outcome, such as which phase caused a failure.

start_time_millisint

Test start timestamp in milliseconds since epoch.

end_time_millisint

Test end timestamp in milliseconds since epoch.

phaseslist[PhaseRecord]

Ordered list of phase execution records.

log_recordslist[LogRecord]

All log entries captured during test execution.

metadatadict

Test-wide metadata: every keyword argument passed to htf.Test(...) plus test_name and the loaded config. See Metadata.

code_infoCodeInfo

Name, docstring and (when capture_source is on) source of the test module.

diagnoseslist[Diagnosis]

All diagnosis results from phase and test diagnosers.

marginalbool or None

Whether the test passed but with marginal measurements.

Test outcomes

Outcome.PASS

All phases passed and all measurements met their validators.

Outcome.FAIL

One or more measurements failed validation, or a phase returned STOP or FAIL_AND_CONTINUE.

Outcome.ERROR

An unhandled exception occurred during test execution.

Outcome.TIMEOUT

A phase exceeded its timeout_s setting.

Outcome.ABORTED

The operator or system aborted the test before completion.

Phase records

Each phase produces a PhaseRecord with its own outcome and measurements.

namestr

Phase function name or overridden name from PhaseOptions.

outcomePhaseOutcome

Phase-level outcome: PASS, FAIL, SKIP, or ERROR.

resultPhaseResult

The PhaseResult returned by the phase function.

measurementsdict

Mapping of measurement names to their outcomes and values.

start_time_millisint

Phase start timestamp.

end_time_millisint

Phase end timestamp.

codeinfoCodeInfo

Source code and location of the phase function.

Metadata

Keyword arguments to htf.Test() end up in test_record.metadata. Use them for a part number, a firmware version, or anything a downstream tool needs. TofuPilot reads part_number, revision_number, batch_number and sub_units (plus procedure_id with upload()).

main.py
import openhtf as htf

def power_on(test):
    return htf.PhaseResult.CONTINUE

def main():
    test = htf.Test(
        power_on,
        test_name="PCB01 functional test",   # replaces the default "openhtf_test"
        part_number="PCB01",
        firmware="1.4.2",
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

config is reserved — OpenHTF fills it with the loaded configuration. Phases can add to the dictionary at run time through test.test_record.metadata[...], as shown below.

Accessing the record

You can access the test record directly within a phase through test.test_record, though this is generally discouraged in favor of using the test.measurements interface.

main.py
import openhtf as htf

def inspect_phase(test):
    # Access test-level metadata
    test.test_record.metadata['operator'] = 'Jane'

    # Check DUT ID
    test.logger.info('Testing DUT: %s', test.dut_id)

    return htf.PhaseResult.CONTINUE

def main():
    test = htf.Test(inspect_phase)
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

JSON output

The most common way to inspect a test record is via JSON output. See Output Callbacks for details on writing test records to files.

main.py
import openhtf as htf
from openhtf.output.callbacks import json_factory

@htf.measures(htf.Measurement('voltage').in_range(3.0, 5.0))
def measure_voltage(test):
    test.measurements.voltage = 3.3

def main():
    test = htf.Test(measure_voltage)
    test.add_output_callbacks(
        json_factory.OutputToJSON('./test_result.json', indent=2)
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

The resulting JSON file contains the complete test record: DUT ID, station ID, outcome, all phase records with their measurements, logs, and timing data. Field-by-field documentation of that file is in the JSON format reference.

From file to database

A JSON file per run is fine on one bench. With several stations you'll want the runs in a database. TofuPilot takes this record as is: tofupilot run uploads it, or add the upload() callback.

On this page

Run it on your stations

$ tofupilot run .
✓ operator UI ready
$ git push
✓ stations updated
✓ runs uploaded

Same OpenHTF script, no code changes.

How it works