Measurements
Enrich each phase with one or more measurements.

Overview
A measurement is a captured value, like a voltage, temperature, or pass/fail condition. Measurements can include numeric limits, units, and outcomes. Each phase can include one or more measurements. These can be numeric, boolean, string, or multi-dimensional arrays.
Integration
With OpenHTF, you simply define the measurements using openhtf.measures
and openhtf.Measurement
, and TofuPilot collects the information automatically.
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
# Decorator to set measurement name, unit and limits
@htf.measures(htf.Measurement("voltage").in_range(3.1,
3.5).with_units(units.VOLT))
# Phase returns a Pass status because measurement (3.3) is within defined
# limits [3.1, 3.5]
def phase_voltage_measure(test):
test.measurements.voltage = 3.3
def main():
test = htf.Test(
phase_voltage_measure,
procedure_id="FVT1",
part_number="PCB1")
with TofuPilot(test):
test.execute(lambda: "PCB1A001")
if __name__ == "__main__":
main()
Measurements properties
- Name
measurements
- Type
- array (optional)
- Description
List of measurements in the phase.
- Name
name
- Type
- string
- Description
Name of one measurement.
- Name
outcome
- Type
- "PASS" | "FAIL" | "UNSET"
- Description
Outcome of the measurement.
- Name
measured_value
- Type
- number | string | boolean | dict (optional)
- Description
Captured value.
- Name
units
- Type
- string | array (optional)
- Description
Units of the value. Examples: Volts, Celsius
- Name
lower_limit
- Type
- number (optional)
- Description
Minimum valid value (only for numbers).
- Name
upper_limit
- Type
- number (optional)
- Description
Maximum valid value (only for numbers).
Numerical
You can use numerical measurement to capture quantities like voltage, resistance, or temperature.
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
@htf.measures(
htf.Measurement("temperature") # Declares the measurement name
.in_range(0, 100) # Defines the lower and upper limits
.with_units(units.DEGREE_CELSIUS) # Specifies the unit
)
def phase_temperature(test):
test.measurements.temperature = 25 # Set the temperature measured value to 25°C
def main():
test = htf.Test(
phase_temperature,
procedure_id="FVT1", # Create the procedure first in the Application
part_number="PCB1",
)
with TofuPilot(test):
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
String
Used to capture serial numbers, firmware versions, or textual responses.
import openhtf as htf
from tofupilot.openhtf import TofuPilot
@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,
procedure_id="FVT1", # Create the procedure first in the Application
part_number="PCB1",
)
with TofuPilot(test):
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Boolean
Used for pass/fail conditions, feature flags, or toggled states.
import openhtf as htf
from tofupilot.openhtf import TofuPilot
@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,
procedure_id="FVT1", # Create the procedure first in the Application
part_number="PCB1",
)
with TofuPilot(test):
test.execute(lambda: "PCB001")
if __name__ == "__main__":
main()
Multi-dimensional
You can capture arrays or time-series data within a single measurement.
import random
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
@htf.measures(
htf.Measurement("current_voltage_resistance_over_time")
.with_dimensions(
units.SECOND, units.VOLT, units.AMPERE
) # Input axes: time, voltage, current
.with_units(units.OHM) # Output unit: resistance in ohms
)
def power_phase(test):
for t in range(100):
timestamp = t / 100
voltage = round(random.uniform(3.3, 3.5), 2)
current = round(random.uniform(0.3, 0.8), 3)
resistance = voltage / current
test.measurements.current_voltage_resistance_over_time[
timestamp, voltage, current
] = resistance
def main():
test = htf.Test(
power_phase,
procedure_id="FVT1",
part_number="PCB01",
)
with TofuPilot(test):
test.execute(lambda: "PCB1A003")
if __name__ == "__main__":
main()
You can open and explore dimension-based measurements by clicking the chart button within the Phases chart on the Run page:

Multiple measurements
You can group several related measurements—whether numerical, string, boolean, or multi-dimensional—within a single test phase.
import random
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
@htf.measures(
htf.Measurement("is_connected").equals(True), # Boolean measure
htf.Measurement("firmware_version").equals("1.2.7"), # String measure
htf.Measurement("input_voltage").in_range(3.2, 3.4).with_units(units.VOLT),
htf.Measurement("input_current").in_range(
maximum=1.5).with_units(units.AMPERE),
)
def phase_multi_measurements(test):
test.measurements.is_connected = True
test.measurements.firmware_version = "1.2.7"
test.measurements.input_voltage = round(random.uniform(3.29, 3.42), 2)
test.measurements.input_current = round(random.uniform(1.0, 1.55), 3)
def main():
test = htf.Test(
phase_multi_measurements,
procedure_id="FVT1",
part_number="PCB01",
)
with TofuPilot(test):
test.execute(lambda: "PCB1A004")
if __name__ == "__main__":
main()

In-app view
Run page
Each test run shows a breakdown of all phases and their associated measurements.

Control chart
You can view measurment trends, go to the Procedure page, click on a phase (e.g., phase_one
), and select the desired measurement. The Control Chart displays limits lower_limit
and upper_limit
and the 6-sigma standard deviation, calculated automatically.
If measurement limits have changed over time, TofuPilot uses the most recent ones for charting.

To unselect a measurement, click its name on the top bar of the page or click on Clear Filter.