Skip to content
Compliance & Traceability

Track Serial Numbers and Sub-Assemblies

Record parent/child serial number relationships in your test data to trace sub-assemblies across boards, modules, and final products.

JJulien Buteau
intermediate7 min readMarch 14, 2026

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.

test_assembly.py
# 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.

test_scan_subunits.py
# 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_nested_assembly.py
# 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.

More Guides

Put this guide into practice