Measurements
Create measurements to capture and validate data within phases.

Overview
Hardware tests are more complex than simple pass/fail checks like in software testing. They often require measuring physical values and comparing them to limits. OpenHTF simplifies logging and validating numeric, string, and boolean values, either individually or in arrays, using built-in decorators.
Numeric
You can define and validate numeric measurements.
main.py
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement("temperature") # Declares the measurement name
.in_range(0, 100) # Defines the validator
.with_units(units.DEGREE_CELSIUS) # Specifies the unit
.with_precision(1) # Rounds to 1 decimal place
)
def phase_temperature(test):
test.measurements.temperature = 25 # Set the temperature value to 25°C
def main():
test = htf.Test(phase_temperature)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Validators
- Name
.in_range(minimum, maximum)
- Type
- number, number
- Description
Ensure the measurement is within the given range.
- Name
.within_percent(value, percent)
- Type
- number, number
- Description
Ensure the measurement is within the given percentage range.
- Name
.equals(value)
- Type
- number
- Description
Ensure the measurement exactly matches the specified value.
- Name
.with_validator(lambda)
- Type
- function → bool
- Description
Apply a custom validator function to the measurement.
Options
- Name
.with_units(units)
- Type
- UnitDescriptor
- Description
Define unit to the measurement (e.g. AMPERE, VOLT, full list here).
- Name
.with_precision(precision)
- Type
- int
- Description
Round the value to the specified precision before validation.
main.py
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement("voltage")
.in_range(maximum=10)
.with_units(units.VOLT)
)
def phase_voltage(test):
test.measurements.voltage = 5.3
@htf.measures(
htf.Measurement("memory")
.equals(8)
.with_units(units.GIGABYTE)
)
def phase_memory(test):
test.measurements.memory = 8
def main():
test = htf.Test(phase_voltage, phase_memory)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
String
You can define and validate string measurements.
main.py
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement("firmware_version")
.equals("1.2.4")
)
def phase_firmware(test):
test.measurements.firmware_version = "1.2.4"
def main():
test = htf.Test(phase_firmware)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Validators
- Name
.equals(value)
- Type
- str
- Description
Ensure the measurement exactly matches the specified value.
- Name
.matches_regex(pattern)
- Type
- str
- Description
Ensure the string matches the specified regex pattern.
- Name
.with_validator(lambda)
- Type
- function → bool
- Description
Apply a custom validator function to the measurement.
Boolean
You can define and validate boolean measurements.
main.py
import openhtf as htf
@htf.measures(
htf.Measurement("is_led_switch_on")
.equals(True)
)
def phase_led(test):
test.measurements.is_led_switch_on = True
def main():
test = htf.Test(phase_led)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Validators
- Name
.equals(value)
- Type
- bool
- Description
Ensure the measurement exactly matches the specified value.
- Name
.with_validator(lambda)
- Type
- function → bool
- Description
Apply a custom validator function to the measurement.
Multiple measurements
You can also use multiple measurements in a single phase.
main.py
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement("is_connected").equals(True),
htf.Measurement("firmware_version").equals("1.2.7"),
htf.Measurement("temperature").in_range(0, 100).with_units(units.DEGREE_CELSIUS),
)
def phase_multi_measurements(test):
test.measurements.is_connected = True
test.measurements.firmware_version = "1.2.7" if test.measurements.is_connected else "N/A"
test.measurements.temperature = 22.5
def main():
test = htf.Test(phase_multi_measurements)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Multidimensional
You can capture data in arrays, like time-series or across categories, with multidimensional measurements.
main.py
import openhtf as htf
from openhtf.util import units
import random
import time
@htf.measures(
htf.Measurement("voltage_over_time")
.with_dimensions(units.SECOND, units.VOLT)
)
def phase_voltage_measurement(test):
for t in range(10):
timestamp = t
voltage = round(random.uniform(3.3, 3.5), 2)
test.measurements.voltage_over_time[timestamp, voltage] = 0
time.sleep(0.1)
def main():
test = htf.Test(phase_voltage_measurement)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Options
- Name
.with_dimensions(*dims)
- Type
- UnitDescriptor
- Description
Set multiple units for multidimensional measurements.
Advanced use cases
You can leverage advanced OpenHTF options to handle more complex phase execution cases.
Marginal
You can mark a measure as marginal to show it’s close to failing, even if it passes.
main.py
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement('resistance')
.with_units('ohm')
.in_range(minimum=5, maximum=17, marginal_minimum=9, marginal_maximum=11)
)
def phase_marginal(test):
test.measurements.resistance = 13
def main():
test = htf.Test(phase_marginal)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Terminal
================= test: openhtf_test outcome: PASS (MARGINAL) =================
Documentation
You can add a description to your measurements.
main.py
import openhtf as htf
@htf.measures(
htf.Measurement("temperature")
.in_range(0, 100)
.doc("This measurement tracks the ambient temperature during the test.")
)
def phase_temperature(test):
test.measurements.temperature = 25
def main():
test = htf.Test(phase_temperature)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Dynamic naming
You can customize measurement names dynamically at execution.
main.py
import openhtf as htf
@htf.measures(
htf.Measurement("test_result_{level}")
.with_args(level="high")
.equals(True)
)
def phase_test(test):
test.measurements.test_result_high = True
def main():
test = htf.Test(phase_test)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Transformation function
You can apply measurement transformation functions before validation.
main.py
import openhtf as htf
@htf.measures(
htf.Measurement("voltage")
.in_range(0, 10)
.with_transform(lambda x: x * 1.1)
.with_units("V")
)
def phase_voltage(test):
test.measurements.voltage = 5 # Value will be transformed to 5.5 before validation
def main():
test = htf.Test(phase_voltage)
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()