Checkpoints & Branching

Control OpenHTF test flow with checkpoints that stop on failure and branch sequences that conditionally execute phases based on diagnosis results.

Stop early on failure or run phases conditionally based on diagnosis results.

A checkpoint phase inspects the outcome of the phases before it. When calibration has failed, the checkpoint stops the test so the long burn-in phase never runs.

  • Test start
  • phase_power
  • phase_calibrate
  • checkpoint("calibration")
  • phase_burn_in10 min
  • Test end

Not every test should run every phase. If calibration fails, there is no point running a 10-minute burn-in. OpenHTF provides two mechanisms for this: checkpoints that stop execution when previous phases fail, and branch sequences that conditionally execute phases based on diagnosis results.

Checkpoints

A checkpoint inspects the outcome of previous phases and decides whether to continue or stop. Place a checkpoint before any expensive phase you want to skip on failure.

main.py
import openhtf as htf
from openhtf.util import checkpoints

@htf.measures(
    htf.Measurement('calibration_offset').in_range(-1, 1)
)
def calibration_phase(test):
    test.measurements.calibration_offset = 5  # Will fail validation

def long_burn_in(test):
    # This should NOT run if calibration failed
    import time
    test.logger.info('Starting 10-minute burn-in')
    time.sleep(600)
    return htf.PhaseResult.CONTINUE

def main():
    test = htf.Test(
        calibration_phase,
        checkpoints.checkpoint('post_calibration'),  # Stops if any previous phase failed
        long_burn_in,
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Since calibration_phase fails its measurement, the checkpoint triggers a STOP and long_burn_in never runs.

Checkpoint types

checkpoint(name)str

Stop the test if any previous phase has a FAIL outcome. This is the most common usage.

PhaseFailureCheckpoint.last(name)str

Stop only if the immediately previous phase failed.

PhaseFailureCheckpoint.all_previous(name)str

Stop if any previous phase in the entire test failed. Same as checkpoint().

PhaseFailureCheckpoint.subtest_previous(name)str

Stop if any previous phase within the current subtest failed.

main.py
import openhtf as htf
from openhtf.util.checkpoints import PhaseFailureCheckpoint

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

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

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

def main():
    test = htf.Test(
        phase_a,
        phase_b,
        PhaseFailureCheckpoint.last('check_b'),  # Only checks phase_b → PASS, continues
        phase_c,
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Stop on first failure

For simpler cases where you want the entire test to stop as soon as any measurement fails, use the stop_on_first_failure test option instead of checkpoints.

main.py
import openhtf as htf

@htf.measures(htf.Measurement('voltage').in_range(0, 5))
def phase_one(test):
    test.measurements.voltage = 10  # Fails

@htf.measures(htf.Measurement('current').in_range(0, 1))
def phase_two(test):
    # This will NOT run
    test.measurements.current = 0.5

def main():
    test = htf.Test(phase_one, phase_two)
    test.configure(stop_on_first_failure=True)
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Subtests

Subtests isolate groups of phases so a failure in one subtest does not stop other subtests from running. Use PhaseResult.FAIL_SUBTEST to fail a subtest without stopping the entire test.

main.py
import openhtf as htf

def wifi_test(test):
    test.logger.info('Testing WiFi')
    return htf.PhaseResult.FAIL_SUBTEST  # Fails this subtest only

def bluetooth_test(test):
    test.logger.info('Testing Bluetooth')
    return htf.PhaseResult.CONTINUE

def main():
    test = htf.Test(
        htf.Subtest('wireless_wifi', wifi_test),
        htf.Subtest('wireless_bluetooth', bluetooth_test),  # Still runs
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Branch sequences

Branch sequences execute phases conditionally based on diagnosis results. Combine them with diagnoses to build adaptive test flows.

main.py
import openhtf as htf
from openhtf.core import diagnoses_lib, measurements
from openhtf.core.phase_branches import BranchSequence, DiagnosisCondition

class CalDiag(diagnoses_lib.DiagResultEnum):
    NEEDS_RECAL = 'needs_recal'

@diagnoses_lib.PhaseDiagnoser(CalDiag)
def cal_check(phase_record):
    for m in phase_record.measurements.values():
        if m.outcome == measurements.Outcome.FAIL:
            return diagnoses_lib.Diagnosis(
                CalDiag.NEEDS_RECAL,
                description='Calibration drift detected',
            )
    return None

@htf.diagnose(cal_check)
@htf.measures(htf.Measurement('offset').in_range(-0.5, 0.5))
def check_calibration(test):
    test.measurements.offset = 1.2  # Fails, triggers NEEDS_RECAL

def recalibrate(test):
    test.logger.info('Running recalibration sequence')
    return htf.PhaseResult.CONTINUE

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

def main():
    test = htf.Test(
        check_calibration,
        BranchSequence(
            DiagnosisCondition.on_any(CalDiag.NEEDS_RECAL),
            recalibrate,  # Only runs if NEEDS_RECAL diagnosed
        ),
        final_test,
    )
    test.execute(lambda: "SN1234")

if __name__ == "__main__":
    main()

Condition types

DiagnosisCondition.on_all(*results)

Execute branch only if ALL specified diagnosis results are present.

DiagnosisCondition.on_any(*results)

Execute branch if ANY of the specified diagnosis results are present.

DiagnosisCondition.on_not_all(*results)

Execute branch if NOT ALL of the specified results are present.

DiagnosisCondition.on_not_any(*results)

Execute branch if NONE of the specified results are present.

On this page

First-pass yield
0%4.1
Track with TofuPilot