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 testimport openhtf as htffrom 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 = 1def 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 assemblyimport openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import TofuPilot# Store scanned serials at module levelscanned_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.31def 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 itimport openhtf as htffrom 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 = 1def 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.