Most hardware products contain sub-assemblies, each with its own serial number. TofuPilot's sub_units feature lets you record which components went into which parent unit, giving you full BOM traceability from a single test script.
Why Sub-Assembly Tracking Matters
A finished product might contain a power supply board, a compute module, and a sensor array. Each has its own serial number and its own test history. When a field failure points to a specific component, you need to know which parent units contain that component.
This is standard practice for IPC-1782 traceability and required in regulated industries. TofuPilot links parent and child serial numbers automatically when you include them in your test runs.
Recording Sub-Unit Serial Numbers
Use the sub_units parameter in TofuPilot to declare which components were installed in the DUT during assembly.
# Record sub-assembly serial numbers during final assembly test
import openhtf as htf
from tofupilot.openhtf import TofuPilot
@htf.measures(
htf.Measurement("system_power_on").in_range(minimum=1, maximum=1),
htf.Measurement("communication_check").in_range(minimum=1, maximum=1),
)
def system_integration_test(test):
test.measurements.system_power_on = 1
test.measurements.communication_check = 1
def main():
test = htf.Test(system_integration_test)
with TofuPilot(
test,
sub_units=[
{"serial_number": "PSU-2026-0441"},
{"serial_number": "CPU-2026-1187"},
{"serial_number": "SNS-2026-0893"},
],
):
test.execute(test_start=lambda: "ASSY-2026-0072")
if __name__ == "__main__":
main()After this test uploads, TofuPilot's unit page for ASSY-2026-0072 shows three linked sub-assemblies. Click any sub-unit serial to see its own test history.
Scanning Sub-Unit Serials During Assembly
In practice, operators scan component serial numbers as they install them. You can collect these in an OpenHTF phase and pass them to TofuPilot.
# Operator scans sub-assembly serials during assembly
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
# Store scanned serials at module level
scanned_sub_units = []
@htf.measures(
htf.Measurement("psu_serial"),
htf.Measurement("cpu_serial"),
)
def scan_components(test):
psu = input("Scan PSU serial: ")
cpu = input("Scan CPU serial: ")
test.measurements.psu_serial = psu
test.measurements.cpu_serial = cpu
scanned_sub_units.append({"serial_number": psu})
scanned_sub_units.append({"serial_number": cpu})
@htf.measures(
htf.Measurement("power_rail_5v").in_range(minimum=4.8, maximum=5.2).with_units(units.VOLT),
htf.Measurement("power_rail_3v3").in_range(minimum=3.1, maximum=3.5).with_units(units.VOLT),
)
def power_validation(test):
test.measurements.power_rail_5v = 5.02
test.measurements.power_rail_3v3 = 3.31
def main():
test = htf.Test(scan_components, power_validation)
with TofuPilot(test, sub_units=scanned_sub_units):
test.execute(test_start=lambda: input("Scan assembly serial: "))
if __name__ == "__main__":
main()Multi-Level Assemblies
For products with nested assemblies (a module inside a board inside a chassis), test each level separately with its own sub-units. TofuPilot builds the hierarchy automatically.
# Test a module, then test the board that contains it
import openhtf as htf
from tofupilot.openhtf import TofuPilot
@htf.measures(
htf.Measurement("module_self_test").in_range(minimum=1, maximum=1),
)
def module_test(test):
test.measurements.module_self_test = 1
@htf.measures(
htf.Measurement("board_communication").in_range(minimum=1, maximum=1),
)
def board_test(test):
test.measurements.board_communication = 1
def main():
# First: test the module by itself
module_serial = "MOD-2026-0551"
t1 = htf.Test(module_test)
with TofuPilot(t1):
t1.execute(test_start=lambda: module_serial)
# Second: test the board, declaring the module as a sub-unit
board_serial = "BRD-2026-0112"
t2 = htf.Test(board_test)
with TofuPilot(t2, sub_units=[{"serial_number": module_serial}]):
t2.execute(test_start=lambda: board_serial)
if __name__ == "__main__":
main()In TofuPilot's dashboard, searching for the board serial shows the module as a sub-unit. Searching for the module serial shows its own test results plus the parent board it was installed in.
BOM Traceability Use Cases
Once sub-assembly links exist in TofuPilot, you can answer questions that matter in production:
- Field failure investigation. A sensor module fails in the field. Search its serial number to find every parent unit that contains the same module type from the same production batch.
- Component recall. A supplier flags a batch of capacitors. If your test phases record component lot numbers as measurements, you can trace which assemblies used them.
- Yield by component. TofuPilot's dashboard shows FPY broken down by any dimension. If a specific sub-assembly batch is causing failures, you'll see it in the data.
Viewing Sub-Assembly Links
Open any unit's page in TofuPilot to see its sub-assembly tree. The page shows:
- Direct child components with their serial numbers
- Each child's own test history (click through to view)
- The parent assembly, if this unit is itself a sub-component
- All test runs for the unit, across every production stage
This gives quality engineers and auditors a single place to trace any component through the entire product hierarchy.