TofuPilotTofuPilot

Unit Under Test (UUT)

Identify hardware units under test with serial numbers, custom metadata, and sub-unit assemblies for full traceability in TofuPilot.

You can identify each unit under test with serial numbers, part numbers, revision numbers, and batch numbers.

TofuPilot Framework stores unit information in test reports for traceability.

Identify Unit

To ensure UUT is identified during a run, TofuPilot adds an automatic Identify Unit phase. This phase uses default_values when provided and waits for user input of at least serial number and part number.

To skip the interactive phase entirely and use default values automatically, see Auto-Identify.

Auto-Identify

You can skip the Identify Unit phase by setting auto_identify: true. TofuPilot uses default_value fields directly — the run starts immediately without operator input.

unit:
  auto_identify: true
  serial_number:
    default_value: "SN00012345"
  part_number:
    default_value: "PCB-MAIN-V2"

Requires serial_number.default_value and part_number.default_value to be set. Optional fields (revision_number, batch_number, sub_units) use their defaults if provided. See use case in Examples.

With auto_identify: true, the Run Again button is disabled — use Run instead.

Serial Number

You can set a unique identifier for each individual unit.

unit:
  serial_number: 
    default_value: "SN00012345"
def identify_unit(unit):
    unit.serial_number = "SN00012345"

TofuPilot Framework requires a serial number for every test run.

Part Number

You can set the unit type or model number.

unit:
  part_number: 
    default_value: "PCB-MAIN-V2"
def set_part(unit):
    unit.part_number = "PCB-MAIN-V2"

TofuPilot Framework requires a part number for every test run.

Revision Number

You can optionally set the revision of the unit.

unit:
  revision_number: 
    default_value: "Rev C"
def set_revision(unit):
    unit.revision_number = "Rev C"

TofuPilot Framework stores revision numbers in reports and syncs them to your Dashboard.

Batch Number

You can optionally set the production batch or lot number.

unit:
  batch_number: 
    default_value: "BATCH-2024-001"
def set_batch(unit):
    unit.batch_number = "BATCH-2024-001"

TofuPilot Framework stores batch numbers in reports and syncs them to your Dashboard.

Sub-units

You can track component serial numbers linked to the main unit under test.

unit:
  sub_units: 
    - label: "Battery"
      serial_number: 
        placeholder: "Scan battery"
        pattern: "^BAT-.*"
    - label: "Motor"
      serial_number: 
        placeholder: "Scan motor"
def test_phase(unit):
    # Dict access (case-insensitive)
    battery_sn = unit.sub_units["battery"]
    motor_sn = unit.sub_units["motor"]

    # Attribute access (lowercase)
    battery_sn = unit.sub_units.battery
    motor_sn = unit.sub_units.motor

    # Iterate all sub-units (keys are lowercase)
    for key, serial in unit.sub_units.items():
        print(f"{key}: {serial}")  # "battery: BAT-...", "motor: MOT-..."

TofuPilot Framework collects sub-unit serial numbers during the Identify Unit phase and makes them available in Python as a dictionary.

Each sub-unit requires a label and optionally a serial_number configuration. The serial_number field supports the same validation options as the main unit fields — see Validation for all available options.

The sub-units must already exist as Units in TofuPilot when creating the Run. Ensure each sub-unit has been tested and registered before referencing it in the assembly. If a sub-unit doesn't exist, the report will be saved locally but won't sync to your Dashboard.

Validation

You can configure validation rules for unit fields.

unit:
  serial_number: 
    min_length: 8
    max_length: 20
    pattern: "^SN\\d{8}$"
  part_number: 
    max_length: 50
    pattern: "^PCB-[A-Z]+-V\\d+$"
  revision_number: 
    pattern: "^Rev [A-Z]$"
  batch_number: 
    pattern: "^BATCH-\\d{4}-\\d{3}$"

TofuPilot Framework trims whitespace, validates length constraints, and checks regex patterns before test execution.

You can use these validation options for each unit field:

OptionTypeDescription
default_valuestringPre-filled value in operator input form
placeholderstringPlaceholder text shown in input field
min_lengthintegerMinimum character length (after trimming)
max_lengthintegerMaximum character length (after trimming)
patternstringRegex pattern for validation

Python

You can set unit information from any phase function by adding unit as a parameter.

def identify_unit(unit, device):
    # Read serial number from device registry
    serial = device.read_register(0x1000)
    unit.serial_number = serial 

    # Derive part number from serial prefix
    if serial.startswith("IX"):
        unit.part_number = "IXRouter-V3"
    elif serial.startswith("SN"):
        unit.part_number = "PCB-MAIN-V2"

TofuPilot Framework passes the unit object to your phase function via dependency injection when you add it as a parameter.

Examples

Unit with Validation

A procedure with default values, placeholders, and regex patterns on unit fields — the operator fills in the Identify Unit form before testing starts.

name: Battery Functional Test
version: 1.0.0

unit:
  serial_number:
    placeholder: "Enter serial number"
    pattern: "^SN\\d{8}$"
  part_number:
    default_value: "PCB-MAIN-V2"
  revision_number:
    default_value: "Rev C"
  batch_number:
    placeholder: "Enter batch number"
    min_length: 5
    max_length: 20

main:
  - key: check_voltage
    name: Check Voltage
    python: phases.check_voltage
    measurements:
      - key: voltage
        name: Battery Voltage
        type: numeric
        unit: V
        limits:
          low: 3.2
          high: 4.2
def check_voltage(m, multimeter):
    m.voltage = multimeter.measure_dc_voltage()

Auto-Identified with Barcode Scanner

A procedure that uses auto_identify with a Python phase that reads the serial number from a connected barcode scanner — typical for automated test stations where units are scanned programmatically.

name: Battery Functional Test
version: 1.0.0

plugs:
  - key: barcode_scanner
    name: Barcode Scanner
    python: plugs.barcode_scanner:BarcodeScanner

unit:
  auto_identify: true
  serial_number:
    default_value: "PENDING"
  part_number:
    default_value: "PCB-MAIN-V2"

main:
  - key: scan_unit
    name: Scan Unit
    python: phases.scan_unit

  - key: check_voltage
    name: Check Voltage
    python: phases.check_voltage
    measurements:
      - key: voltage
        name: Battery Voltage
        type: numeric
        unit: V
        limits:
          low: 3.2
          high: 4.2
import serial

class BarcodeScanner:
    def __init__(self):
        self.connection = serial.Serial("/dev/ttyUSB0", baudrate=9600)

    def scan(self):
        return self.connection.readline().decode().strip()
def scan_unit(unit, barcode_scanner):
    unit.serial_number = barcode_scanner.scan()
def check_voltage(m, multimeter):
    m.voltage = multimeter.measure_dc_voltage()

How is this guide?