Writing the software for a production test fixture
The hardware fixture is done: pogo pins land on the test points and the board sits square. Then someone has to decide what the computer does once the board is clamped down. A bench script that worked for the engineer who wrote it becomes a problem when a different person runs it, a board fails halfway through, and nobody can tell which unit was tested against which firmware.
The fixture’s software is a small product of its own. It is also easier to get right than people expect, because almost all of it already exists as open-source tooling.
Decide what the test must prove
A functional test is not a repeat of the design validation. It answers one question per board: was this unit built correctly? That points to a short list of checks, most of which catch assembly faults rather than design faults.
- Power. Supply rails come up to the expected voltage with a sane current draw. A short or a missing part usually shows here first.
- Programming. The firmware loads and reads back identically.
- Communication. The processor answers on its serial or USB port, so you know the clock, the reset line and the debug path all work.
- Peripherals. Each sensor, radio, memory or driver on the board is exercised once. A sensor that returns an ID register has at least proven its bus connection.
- Identity. The unit gets a serial number, and the result is stored against it.
Everything on that list needs a test point, a connector pin or a firmware hook. If the board is still in layout, what test points and programming pads a board needs is the place to start. Adding a point costs a pad on the board; leaving it off can cost a fixture respin.
Program and verify before anything else
Order matters. Program first, because every later check can then use test firmware that exposes the board to the script. A good test image has a command interface over UART or USB that lets the script ask “read this sensor” or “toggle this pin” and get an answer.
Do not trust a successful programming exit code alone. OpenOCD’s program command accepts preverify and verify options, and its flash verify_image command compares an image against the target’s flash and returns pass or fail. pyOCD gives you similar flash programming from a Python scripting API and supports CMSIS-Pack device definitions, which helps when a part is not built into the tool. Either way, the point is to read the flash back and compare it, and to treat a mismatch as a failed board rather than a retry.
The test image and the shipping image are often different. Decide early whether the fixture programs the final firmware after the tests pass, or whether the test image is replaced in a second step. Both work. The risk is a board that passes with test firmware and ships with nothing, so the last step should always be a verification of whatever is on the chip when the board leaves the fixture. How unique serial numbers and keys get written at that stage is covered in provisioning serial numbers and keys on the production line.
Use a test runner, not a long script
The common beginner structure is one Python file that runs top to bottom, prints “OK”, and crashes on the first surprise. It works on the first day. It stops being maintainable the first time you add a second board variant or need to run a single check in isolation.
pytest already solves most of this. Its fixtures manage long-lived resources, such as a serial port, a power supply or a debug probe, and clean them up even when a test fails. Parametrization lets one test function run against every rail or every channel with a table of limits. Assertion output shows the measured value next to the limit, which is what an operator or an engineer reading a failure report actually needs. And the runner is mainstream, so the next engineer will already know it.
Structure the suite in the order the board is brought up. Power checks come first and abort the run if they fail, so the script never tries to talk to a board that has a rail shorted to ground. Stop-on-first-failure for those early checks protects the board and the instruments. Later checks can all run, so one report lists every failed peripheral instead of just the first.
Talking to instruments
If the fixture uses bench instruments, such as a programmable supply, a multimeter or a scope, PyVISA controls measurement devices through one interface regardless of whether they connect by GPIB, serial, USB or Ethernet. Most test instruments accept text commands, so a measurement is a short string sent and a number read back.
For many boards the fixture does not need bench instruments at all. A microcontroller’s own ADC, read through the test firmware, can check rail voltages to a useful tolerance, and a few GPIO-controlled relays or analog switches can route signals. That keeps the fixture small and the cost of each additional unit low. Use external instruments where the measurement needs to be better than the board’s own ADC can offer, such as when you are checking a regulator’s accuracy rather than simply confirming that it is alive.
Whatever you use, calibrate the fixture, not just the board. Probe contact resistance, cable drops and the reference of the measurement all shift the numbers. Put a known-good “golden” board in the fixture periodically and confirm it still reads the same values. When a limit starts to drift on every board at once, the fixture is usually the cause, not the line. The mechanical side of that wear is covered in designing a pogo-pin test fixture that lasts.
Make the result traceable
A pass is only useful if you can find it again. For every board, log at least:
- The serial number or unique ID read from the board.
- The firmware version and the test-script version.
- Each measured value with its limit, not just pass or fail.
- A timestamp, and which fixture ran the test.
Write the record as a plain file, such as CSV or JSON, one per board. A database can come later. Plain files survive a laptop swap and can be attached to a shipment, and customers asking “what did you test on unit 0412?” tend to ask years afterwards.
Make failure impossible to miss. The operator should see a large pass or fail, and a failed board should be set aside physically, not left to be reread later. Do not give the script a way to skip a check without leaving a mark in the log. If a limit is wrong, change the limit, in version control, with a reason.
What goes wrong in practice
- Limits copied from the datasheet. A typical value is not a limit. Set limits from the datasheet’s guaranteed range plus the measurement error of the fixture, and widen them only with a reason.
- Test firmware that drifts from the product. The test image is built from the same repository and tag as the release, or it tests something that does not ship.
- No retry policy. Decide in advance whether a contact fault gets one automatic retest. A silent unlimited retry loop hides a worn probe.
- Operator-dependent steps. If the result depends on how the board is seated, the fixture mechanics need fixing, not the instructions.
How we approach it
We write the test plan from the schematic and the bring-up notes, build the fixture and its script together, and hand over the source so the test can be rerun and changed without us. If you send the schematic, the firmware’s debug interface and a list of what must be proven on every unit, we can tell you what the fixture needs to look like.
If your board works on the bench but nobody can say how to prove that a hundred more do, we would build the fixture and the test script around your actual board.
Tools for this topic
- Assembly quote readiness checkDrop Gerbers, BOM and placement file; see what is missing or inconsistent before you ask for a quote.
- Gerber viewerDrop a fab .zip or Gerber and drill files and see the board: realistic top and bottom render, layers, size and parts overlay. Drawn in your browser, nothing uploaded.
Related notes
- Designing a pogo-pin test fixture that lastsPin choice, tip style, pitch, and alignment decisions that determine whether a bed-of-nails fixture gives repeatable results or wears out fast.
- Membrane switch overlay design checklistWhat to settle before a membrane switch overlay goes to a fabricator: tail exit, venting, domes, material, shielding and enclosure fit, with reasons.
- What test points and programming pads a board needsWhich signals to bring out for programming, debug and production test, so a board can be flashed and checked on a fixture without a respin.