Skip to content
Getting Started

Add Measurements with Limits

A complete reference for OpenHTF measurement types, validators, and units, with code examples for numeric ranges, exact matches, percentages, and marginal.

JJulien Buteau
beginner10 min readMarch 14, 2026

Every measurement in a manufacturing test needs three things: a name, a value, and limits that define pass or fail. OpenHTF provides built-in validators for numeric ranges, exact matches, percentages, and regex patterns. When you log these measurements through TofuPilot, you get FPY, Cpk, and control charts automatically. This guide covers every measurement type with working code.

Measurement Validators

OpenHTF has six built-in validators:

ValidatorUse CaseExample
.in_range(min, max)Value within boundsVoltage, current, resistance
.in_range(minimum=x)Value above minimumSignal strength, gain
.in_range(maximum=x)Value below maximumLatency, noise floor
.equals(value)Exact matchFirmware version, boolean flags
.within_percent(target, pct)Value within percentage of targetCrystal frequency, calibrated sensors
.matches_regex(pattern)String matches regexMAC address, serial number format

Numeric Range: .in_range()

The most common validator. Pass if the value falls between lower and upper limits.

measurements/numeric_range.py
import openhtf as htf
from openhtf.util import units


@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT)
    .doc("3.3V supply rail voltage"),
    htf.Measurement("rail_5v0")
    .in_range(4.8, 5.2)
    .with_units(units.VOLT)
    .doc("5.0V supply rail voltage"),
    htf.Measurement("rail_1v8")
    .in_range(1.7, 1.9)
    .with_units(units.VOLT)
    .doc("1.8V core rail voltage"),
    htf.Measurement("idle_current")
    .in_range(0.05, 0.25)
    .with_units(units.AMPERE)
    .doc("Board idle current draw"),
)
def test_power_rails(test):
    test.measurements.rail_3v3 = 3.31
    test.measurements.rail_5v0 = 5.01
    test.measurements.rail_1v8 = 1.82
    test.measurements.idle_current = 0.12

One-Sided Limits

Use keyword arguments for minimum-only or maximum-only limits.

measurements/one_sided.py
import openhtf as htf


# Minimum only: pass if value >= -80
@htf.measures(
    htf.Measurement("signal_strength")
    .in_range(minimum=-80)
    .doc("Wi-Fi signal strength in dBm"),
)
def test_signal(test):
    test.measurements.signal_strength = -65


# Maximum only: pass if value <= 100
@htf.measures(
    htf.Measurement("response_time")
    .in_range(maximum=100)
    .doc("Response latency in milliseconds"),
)
def test_latency(test):
    test.measurements.response_time = 42

Exact Match: .equals()

Pass if the value exactly matches. Works with strings, booleans, and numbers.

measurements/exact_match.py
import openhtf as htf


# String match
@htf.measures(
    htf.Measurement("firmware_version")
    .equals("2.1.0")
    .doc("Expected firmware version string"),
)
def test_firmware(test):
    test.measurements.firmware_version = "2.1.0"


# Boolean match
@htf.measures(
    htf.Measurement("led_on")
    .equals(True)
    .doc("Power LED is illuminated"),
    htf.Measurement("error_flag")
    .equals(False)
    .doc("No error flags set"),
)
def test_indicators(test):
    test.measurements.led_on = True
    test.measurements.error_flag = False

Percentage Tolerance: .within_percent()

Pass if the value is within a percentage of a target. Useful for calibrated components.

measurements/percentage.py
import openhtf as htf
from openhtf.util import units


@htf.measures(
    # 8MHz crystal, 1% tolerance -> 7.92MHz to 8.08MHz
    htf.Measurement("clock_freq")
    .within_percent(8_000_000, 1.0)
    .with_units(units.HERTZ)
    .doc("8MHz crystal oscillator frequency"),
    # 10kOhm resistor, 5% tolerance -> 9.5kOhm to 10.5kOhm
    htf.Measurement("pullup_resistance")
    .within_percent(10_000, 5.0)
    .with_units(units.OHM)
    .doc("I2C pullup resistor value"),
)
def test_components(test):
    test.measurements.clock_freq = 8_000_100
    test.measurements.pullup_resistance = 9_850

.within_percent(target, percent) is equivalent to .in_range(target * (1 - pct/100), target * (1 + pct/100)) but clearer in intent.

Regex Match: .matches_regex()

Pass if the string matches a regular expression. Useful for format validation.

measurements/regex.py
import openhtf as htf


@htf.measures(
    # MAC address format: AA:BB:CC:DD:EE:FF
    htf.Measurement("mac_address")
    .matches_regex(r"^([0-9A-F]{2}:){5}[0-9A-F]{2}$")
    .doc("Board MAC address format"),
    # Semantic version: X.Y.Z
    htf.Measurement("fw_version")
    .matches_regex(r"^\d+\.\d+\.\d+$")
    .doc("Firmware version format"),
)
def test_strings(test):
    test.measurements.mac_address = "AA:BB:CC:DD:EE:FF"
    test.measurements.fw_version = "2.1.0"

Marginal Limits

OpenHTF supports marginal limits (inner limits within the pass range). A measurement between the marginal limit and the spec limit passes but is flagged as marginal. This catches measurements that are drifting toward failure.

measurements/marginal.py
import openhtf as htf
from openhtf.util import units


@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(
        minimum=3.2,
        maximum=3.4,
        marginal_minimum=3.22,
        marginal_maximum=3.38,
    )
    .with_units(units.VOLT)
    .doc("3.3V rail with marginal band"),
)
def test_marginal_voltage(test):
    # 3.21V passes but is flagged as marginal (between 3.20 and 3.22)
    # 3.25V passes normally (within marginal limits)
    # 3.19V fails (below 3.20)
    test.measurements.rail_3v3 = 3.21
ValueStatusExplanation
3.25PassWithin marginal limits
3.21MarginalBetween spec limit (3.20) and marginal limit (3.22)
3.39MarginalBetween marginal limit (3.38) and spec limit (3.40)
3.19FailBelow spec limit (3.20)
3.41FailAbove spec limit (3.40)

Units Reference

OpenHTF provides standard SI units via from openhtf.util import units. Always use .with_units() for numeric measurements. It feeds into TofuPilot analytics and makes reports readable.

UnitOpenHTF ConstantUse Case
Voltunits.VOLTVoltage rails, analog signals
Ampereunits.AMPERECurrent draw
Ohmunits.OHMResistance, impedance
Hertzunits.HERTZFrequency, clock signals
Celsiusunits.DEGREE_CELSIUSTemperature
Secondunits.SECONDTime, latency
Wattunits.WATTPower consumption

Multiple Measurements Per Phase

Group related measurements in one phase. This keeps the test report organized and the test time efficient.

measurements/multi.py
import openhtf as htf
from openhtf.util import units


@htf.measures(
    htf.Measurement("rail_3v3").in_range(3.2, 3.4).with_units(units.VOLT),
    htf.Measurement("rail_5v0").in_range(4.8, 5.2).with_units(units.VOLT),
    htf.Measurement("idle_current").in_range(0.05, 0.25).with_units(units.AMPERE),
    htf.Measurement("led_on").equals(True),
    htf.Measurement("firmware").equals("2.1.0"),
)
def test_board_basics(test):
    test.measurements.rail_3v3 = 3.31
    test.measurements.rail_5v0 = 5.01
    test.measurements.idle_current = 0.12
    test.measurements.led_on = True
    test.measurements.firmware = "2.1.0"

Guideline: Group measurements that are logically related (all power rails in one phase, all communication checks in another). Split into separate phases if they require different instruments or have different timeouts.

Setting Limits from Datasheets

Start with the datasheet absolute maximum and minimum ratings. Then tighten based on production data.

SourceUse ForExample
DatasheetInitial limits3.3V regulator: 3.135V to 3.465V (5% tolerance)
Production data (100+ units)Refined limits3-sigma from measured distribution
Customer requirementsMandatory limitsSpecified in test specification
measurements/limits_from_datasheet.py
import openhtf as htf
from openhtf.util import units


# Datasheet says: 3.3V +/- 5% = 3.135V to 3.465V
# Production data shows: mean=3.30, stdev=0.015
# 3-sigma: 3.255 to 3.345 (tighter, use these)
@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(3.255, 3.345)
    .with_units(units.VOLT)
    .doc("3.3V rail (3-sigma from production data)"),
)
def test_refined_limits(test):
    test.measurements.rail_3v3 = 3.31

More Guides

Put this guide into practice