Diagnoses

Use OpenHTF diagnoses to analyze results after measurement validation, classify failure modes, and drive conditional execution between phases.

Analyze measurements after validation to classify failure modes and drive conditional logic.

After a phase validates its measurements, a diagnoser inspects the results and emits a diagnosis such as OVERVOLTAGE with a priority. A branch sequence then runs a corrective phase only when that diagnosis is present.

  • Test start
  • phase_voltagevoltage = 10.6 V, limit 10 V
  • @diagnose(VoltageDiagnoser)inspects the phase record
  • BranchSequenceif OVERVOLTAGE
  • phase_discharge
  • Test end

Measurements tell you what happened. Diagnoses tell you why. After a phase validates its measurements, diagnosers inspect the results and produce structured diagnosis objects. These can classify failure modes, set priorities, and trigger conditional execution of later phases.

Defining diagnosis results

Create a DiagResultEnum to define the possible outcomes of your diagnosers. Each value must be unique across all diagnosers in the same test.

main.py
import enum
import openhtf as htf
from openhtf.core import diagnoses_lib

class PowerDiag(diagnoses_lib.DiagResultEnum):
    OVERVOLTAGE = 'overvoltage'
    UNDERVOLTAGE = 'undervoltage'
    OVERCURRENT = 'overcurrent'

Phase diagnosers

A phase diagnoser runs after a single phase completes. It receives the PhaseRecord and returns one or more Diagnosis objects.

main.py
import enum
import openhtf as htf
from openhtf.core import diagnoses_lib, measurements

class VoltageDiag(diagnoses_lib.DiagResultEnum):
    HIGH = 'voltage_high'
    LOW = 'voltage_low'

@diagnoses_lib.PhaseDiagnoser(VoltageDiag)
def voltage_diagnoser(phase_record):
    for name, measurement in phase_record.measurements.items():
        if measurement.outcome == measurements.Outcome.FAIL:
            if measurement.measured_value.value > 12:
                return diagnoses_lib.Diagnosis(
                    VoltageDiag.HIGH,
                    description='Voltage exceeds 12V limit',
                    is_failure=True,
                )
            else:
                return diagnoses_lib.Diagnosis(
                    VoltageDiag.LOW,
                    description='Voltage below minimum threshold',
                    is_failure=True,
                )
    return None

@htf.diagnose(voltage_diagnoser)
@htf.measures(
    htf.Measurement('voltage').in_range(3.0, 12.0)
)
def measure_voltage(test):
    test.measurements.voltage = 15.0  # Will trigger HIGH diagnosis

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

if __name__ == "__main__":
    main()

Test diagnosers

A test diagnoser runs after all phases complete. It receives the full TestRecord and the DiagnosesStore containing all phase-level diagnoses.

main.py
import openhtf as htf
from openhtf.core import diagnoses_lib
from openhtf.core.test_record import PhaseOutcome

class TestDiag(diagnoses_lib.DiagResultEnum):
    BOARD_DEFECTIVE = 'board_defective'

@diagnoses_lib.TestDiagnoser(TestDiag)
def board_diagnoser(test_record, diagnoses_store):
    failed_phases = [
        p for p in test_record.phases
        if p.outcome == PhaseOutcome.FAIL
    ]
    if len(failed_phases) >= 2:
        return diagnoses_lib.Diagnosis(
            TestDiag.BOARD_DEFECTIVE,
            description='Multiple phase failures indicate defective board',
            is_failure=True,
        )
    return None

def phase_one(test):
    return htf.PhaseResult.FAIL_AND_CONTINUE

def phase_two(test):
    return htf.PhaseResult.FAIL_AND_CONTINUE

def main():
    test = htf.Test(phase_one, phase_two)
    test.configure(diagnosers=[board_diagnoser])
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Diagnosis properties

resultDiagResultEnum

The diagnosis result value from your enum.

descriptionstr

Human-readable explanation of the diagnosis.

is_failurebool

Whether this diagnosis should cause the phase or test to fail.

priorityDiagPriority

Importance level: HIGHEST, NORMAL (default), or INFORMATIVE.

Conditional measurement validation

You can attach validators that only apply when specific diagnoses are present, using .validate_on().

main.py
import openhtf as htf
from openhtf.core import diagnoses_lib

class ModeDiag(diagnoses_lib.DiagResultEnum):
    HIGH_POWER = 'high_power'
    LOW_POWER = 'low_power'

@htf.measures(
    htf.Measurement('current')
    .in_range(0.1, 1.0)  # Default validator
    .validate_on({ModeDiag.HIGH_POWER: htf.Measurement('current').in_range(1.0, 5.0)})
)
def measure_current(test):
    test.measurements.current = 3.0

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

if __name__ == "__main__":
    main()

When HIGH_POWER is diagnosed, the stricter 1.0–5.0 range replaces the default 0.1–1.0 range.

On this page

First-pass yield
0%4.1
Track with TofuPilot