What Is Functional Testing for Hardware with TofuPilot
Functional testing validates that a hardware product behaves correctly as a complete system. Unlike in-circuit testing (ICT), which checks individual components and solder joints, functional testing treats the board or product as a black box and verifies its inputs and outputs. This guide covers what functional testing involves, how it compares to other test methods, and how to build functional tests in Python with TofuPilot.
Functional Testing vs Other Methods
| Method | What It Tests | How | Finds |
|---|---|---|---|
| ICT (In-Circuit Test) | Individual components | Bed-of-nails fixture, powered | Opens, shorts, wrong values |
| Flying probe | Individual components | Moving probes, unpowered/powered | Same as ICT, no fixture needed |
| Functional test (FCT) | System behavior | Powered, exercised through interfaces | Integration bugs, firmware issues, performance |
| Boundary scan (JTAG) | Digital IC connections | Through JTAG chain | Digital connectivity |
ICT tells you the right parts are soldered correctly. Functional testing tells you the product actually works.
What Functional Tests Cover
A functional test exercises the product through its real interfaces: power input, communication ports, sensors, actuators, and user controls.
| Category | Example Checks |
|---|---|
| Power | Startup current, voltage regulation, power sequencing |
| Communication | UART, SPI, I2C, CAN, Ethernet respond correctly |
| Analog | ADC readings match known inputs within tolerance |
| Digital I/O | GPIO states match expected logic levels |
| Actuators | Motors, relays, LEDs respond to commands |
| Firmware | Version check, self-test pass, boot time |
| RF (if applicable) | Transmit power, receive sensitivity, frequency accuracy |
Prerequisites
- Python 3.10+
- OpenHTF installed (
pip install openhtf) - TofuPilot Python SDK installed (
pip install tofupilot)
Step 1: Define Functional Test Phases
Each functional check becomes an OpenHTF phase. Group related checks together but keep phases focused enough that a failure points to a specific subsystem.
import openhtf as htf
from openhtf.util import units
@htf.measures(
htf.Measurement("boot_time_ms")
.in_range(maximum=2000)
.with_units(units.MILLISECOND),
htf.Measurement("firmware_version").equals("1.3.0"),
)
def phase_power_and_boot(test):
"""Power up the DUT and verify boot sequence."""
test.measurements.boot_time_ms = 1240
test.measurements.firmware_version = "1.3.0"
@htf.measures(
htf.Measurement("uart_loopback").equals("PASS"),
htf.Measurement("i2c_sensor_id").equals("0x68"),
)
def phase_communication(test):
"""Verify communication interfaces respond correctly."""
test.measurements.uart_loopback = "PASS"
test.measurements.i2c_sensor_id = "0x68"
@htf.measures(
htf.Measurement("adc_channel_0_V")
.in_range(minimum=2.45, maximum=2.55)
.with_units(units.VOLT),
htf.Measurement("adc_channel_1_V")
.in_range(minimum=1.60, maximum=1.70)
.with_units(units.VOLT),
)
def phase_analog_inputs(test):
"""Apply known voltages and verify ADC readings."""
test.measurements.adc_channel_0_V = 2.50
test.measurements.adc_channel_1_V = 1.65Step 2: Run and Log Results
Connect the test to TofuPilot. Every unit's functional test result uploads automatically with full measurement detail.
from tofupilot.openhtf import TofuPilot
test = htf.Test(
phase_power_and_boot,
phase_communication,
phase_analog_inputs,
)
with TofuPilot(test):
test.execute(test_start=lambda: input("Scan serial number: "))Step 3: Track Results in TofuPilot
TofuPilot tracks functional test results automatically. Open the Analytics tab to see:
- First pass yield for each functional test procedure
- Failure Pareto showing which phases fail most often (power? communication? analog?)
- Measurement distributions with limit overlays to spot tightening trends
- Station comparison if you run the same test on multiple stations
This data helps you decide where to invest. If 80% of functional test failures come from one phase, that's where to focus your design or process improvement.
When to Use Functional Testing
| Scenario | Use FCT? |
|---|---|
| PCBA with firmware | Yes, after SMT and programming |
| Simple passive board | No, ICT or flying probe is sufficient |
| Assembled product with sensors/actuators | Yes, as EOL test |
| Safety-critical product | Yes, with documented test procedure |
| High-volume, low-complexity | Maybe, depends on field failure cost |
Functional testing adds cycle time, but it catches the integration failures that ICT cannot. For products with firmware, communication interfaces, or analog circuits, it's the test stage that matters most.