Decorators
Learn how to use OpenHTF decorators to enhance your test phases with measurements, hardware plugins, and execution configuration.
Last updated · Verified with OpenHTF 1.6.1
Learn how to use OpenHTF decorators to enhance your test phases.
Decorators stack on a phase function. PhaseOptions configures execution, measures declares the measurements the phase records, and plug injects the hardware plug the phase receives as an argument.
- @htf.PhaseOptions(timeout_s=30)execution: 30 s timeout
- @htf.measures(Measurement("voltage"))
- @htf.plug(dmm=MultimeterPlug)
- def phase_voltage(test, dmm)
Python decorators modify function behavior without changing their code. In OpenHTF, decorators add functionality to test phases like declaring measurements, injecting hardware plugins, and configuring execution. They're applied using the @ symbol before function definitions:
@decorator_function
def my_function():
passKey decorators
OpenHTF provides several essential decorators that make test writing more powerful and organized:
1. Declaring measurements
The @htf.measures decorator is used to declare what measurements a phase will capture and validate:
@htf.measures(
htf.Measurement("temperature")
.in_range(0, 100)
.with_units(units.DEGREE_CELSIUS)
.with_precision(1)
)
def measure_temperature(test):
test.measurements.temperature = 25.52. Hardware plugin injection
The @htf.plug decorator injects hardware or software plugins into your test phases:
@htf.plug(multimeter=MultimeterPlug)
def test_voltage(test, multimeter):
voltage = multimeter.measure_voltage()
test.measurements.voltage = voltage3. Phase configuration
The @htf.PhaseOptions decorator configures how a phase should execute:
@htf.PhaseOptions(timeout_s=10, repeat_limit=3)
def retry_phase(test):
# Phase will timeout after 10 seconds and can retry up to 3 times
return htf.PhaseResult.CONTINUECombining
OpenHTF decorators can be combined to create powerful test phases:
@htf.measures(
htf.Measurement("firmware_version").equals("1.2.4"),
htf.Measurement("connection_status").equals(True)
)
@htf.plug(device=DeviceConnection)
@htf.PhaseOptions(timeout_s=30)
def verify_device_connection(test, device):
test.measurements.connection_status = device.is_connected()
test.measurements.firmware_version = device.get_firmware_version()Enhanced example
Let's enhance our first test to demonstrate decorator usage:
import openhtf as htf
@htf.measures(
htf.Measurement("greeting_message").with_validator(
lambda msg: "Hello" in msg
)
)
@htf.PhaseOptions(timeout_s=5)
def hello_world_with_measurement(test):
message = "Hello world!"
print(message)
test.measurements.greeting_message = message
def main():
test = htf.Test(hello_world_with_measurement)
test.execute(lambda: "SN1234")
if __name__ == '__main__':
main()This enhanced version demonstrates:
- Measurement validation using
@htf.measures - Phase timeout using
@htf.PhaseOptions - Custom validation with lambda functions
Understanding these decorators is crucial for building robust OpenHTF tests that can validate measurements, interact with hardware, and handle various execution scenarios.
Dynamic configuration
Python decorators are callables, which means you can apply them at runtime instead of with the @ syntax: htf.measures(m)(phase) returns the decorated phase. This is how you build phases whose limits come from a config file, a product database or operator input.
import openhtf as htf
def phase_resistance_test(test):
test.measurements.resistance = 10.5
def main():
limits = {"min": 5, "max": 17} # e.g. loaded from YAML per part number
measurement = htf.Measurement("resistance").in_range(limits["min"], limits["max"])
configured_phase = htf.PhaseOptions(timeout_s=10)(
htf.measures(measurement)(phase_resistance_test)
)
test = htf.Test(configured_phase)
test.execute(lambda: "SN1234")
if __name__ == "__main__":
main()The same works for @htf.plug. A worked measurement example is under Callable decorators.
Other decorators
Beyond the three above, OpenHTF exposes:
@htf.diagnose(*diagnosers)Attach phase diagnosers that classify the phase's results.
@htf.monitors(name, func, units=, poll_interval_ms=)Sample a value in a background thread while the phase runs — see Monitors.
@CONF.save_and_restore(**overrides)Temporarily override configuration values for one phase.
@CONF.inject_positional_argsFill a plug's __init__ arguments from configuration keys of the same name.
phase.with_args(**kwargs) / phase.with_plugs(**plugs)Not decorators but the same idea: return a copy of a phase with template arguments or plug placeholders filled in. Used in the with_plugs example.
Related
Multi-station
Run OpenHTF on several test stations and see them from one place — the built-in dashboard_server, multicast station discovery, station_server history, configuration per station, and where the built-in tooling stops.
Overview
Runnable OpenHTF example scripts, one per feature — hello world, measurements, plugs, phase groups, branches, checkpoints, repeat, stop on first failure, custom JSON output, Operator UI — each explained line by line.