Once the rig has power control, console access, and a way to provision the DUT, the next step is writing tests against it.
A First Test
The easiest place to start is to trigger a real event through a real interface and watch what the firmware does.
UART is the lowest-friction option:
import time
import serial
def run_start_test(port="/dev/ttyUSB0", baudrate=115200, timeout=5):
with serial.Serial(port, baudrate=baudrate, timeout=0.1) as ser:
ser.reset_input_buffer()
ser.write(b"START\n")
ser.flush()
deadline = time.time() + timeout
while time.time() < deadline:
line = ser.readline().decode("utf-8", errors="replace").strip()
if not line:
continue
if "OK" in line:
return True
if "ERROR" in line:
return False
raise TimeoutError("DUT did not respond within timeout")As the rig matures, tests can drive real-world sequences: a button held for 500 ms, a sensor crossing a threshold, a bus going silent for three seconds, or a device rebooting mid-transaction. These are hard to reproduce reliably by hand, and nearly impossible to cover with CPU-only simulation.
Wiring Tests into CI
Once the tests pass locally, the next step is to run them on every change. The simplest setup is a self-hosted CI runner on the management node. GitHub Actions, GitLab Runner, and most other CI platforms support that model.
A push triggers a workflow that builds the firmware, flashes or netboots the DUT, runs the test suite, captures logs, and reports the results back to the PR.
What You Outgrow
A breadboard prototype with a Pi, a relay board, a USB UART hub, and a small MCU as a signal router gets you a long way, and you can put it together in a few days. It does have limits you'll hit sooner or later:
- No electrical protection if you're relying on relays
- No power measurement
- Custom wiring per target device
- No protection against bus contention
- Limited scaling once you have many boards and many users
- A growing share of your time spent testing the test setup itself
The next iteration is usually a proper PCB power board paired with a dedicated signal router. The breadboard prototype is what de-risks that PCB and tells you exactly what's going to break, before the hardware becomes expensive to change.
Reference Hardware
A representative parts list for the prototype:
| Component | Example | Notes |
|---|---|---|
| Management node | Raspberry Pi 4 | Any Linux SBC can work |
| Relay | 4 or 8 port relay board | Cheap hard on/off control |
| USB UART hub | CH9344 or CH348 | Stable names need udev rules |
| Signal router MCU | Pico, Pico 2, STM32, ESP32 | Choose what your team can maintain |
| Debug probe | Pico CMSIS-DAP | Good enough for many MCU targets |
| Logic analyzer | Generic USB analyzer | Useful from day one |
| Pull-up resistors | 4.7k ohm | Common I2C starting point |
| Managed switch | VLAN-capable | Needed for isolated netboot |