"Knows Python" on a test floor means five specific things: talk to an instrument, survive a hardware failure without crashing the station, run the code on a station PC that isn't a laptop, use Git for changes and releases, and get a run with measurements and limits into TofuPilot. Everything else is optional. This checklist lists the five, what each looks like at the bench, and how to verify it in an interview or in week one.
The Five Skills
Print the table. Tick it in the interview, then tick it again on the Friday of week one. A candidate who's honest about a gap is more useful than one who claims all five.
| Skill | What it looks like in practice | How to verify |
|---|---|---|
| Instrument I/O (PyVISA, SCPI, serial) | Opens a resource by VISA address, sends *IDN?, parses the reply into a float. Knows write, query and read are three different things. Has used pyserial for a DUT console at 115200 baud. | Interview: give them a DMM address and ask for a DC voltage read on the whiteboard. Week one: they write a plug for one bench instrument and it returns a number. |
| Exceptions around hardware | Sets a timeout on every resource. Retries a flaky query a bounded number of times. Closes the instrument in close() even when the phase failed. Reports a VisaIOError as ERROR, not FAIL. | Interview: ask what the station does when the DMM cable comes out mid-run. Week one: pull the cable during their phase and watch. |
| Packaging and environments | Creates a venv, pins versions in requirements.txt, installs on a clean Windows station PC without editing PATH by hand. Knows "works on my laptop" isn't done. | Interview: ask how they'd get code onto a station with no internet. Week one: they install their station on the spare PC from the README alone. |
| Git basics | Branches for a change, opens a pull request, gets a review, tags a release (v1.4.0) and can say which tag runs on which station. | Interview: ask about the last thing they reverted and how. Week one: their first limit change lands as a reviewed pull request, not a file copied over the network share. |
| Data flow | Declares measurements with units and validators in procedure.yaml, runs with --upload, opens the run page for that unit in TofuPilot, reads FPY and Cpk on the procedure page instead of building a spreadsheet. | Interview: ask what they'd open first when yield drops on a Monday. Week one: they find their own runs in TofuPilot and explain one Cpk value to you. |
Three of the five are ordinary software hygiene. The two that separate a test engineer from a generalist developer are instrument I/O and hardware exceptions. Hire for those two and teach the other three during the first week.
Instrument I/O is the one to probe
Every other skill can be learned from a README. Instrument I/O needs a bench, an instrument that lies, and someone who's been bitten before. Ask about termination characters, about a query that returned the previous answer, about the difference between a GPIB timeout and a socket timeout.
The good candidates have a story for each. The PyVISA docs cover the mechanics, and a candidate who's read them will say so.
Exceptions are where stations die
A phase that raises and leaves the DMM half-configured costs you the next unit as well as this one. Ask for the three-part answer: timeout on open, bounded retry on read, cleanup on close.
A bare except that swallows the error is how a station reports PASS on a disconnected cable. Listen for whether the candidate knows the difference between a unit that failed and a station that errored.
What They Don't Need
A job description that lists everything Python can do filters out the people you want. The job description guide covers the posting itself. This is the short list of what to leave off.
| Not needed | Why |
|---|---|
| GUI frameworks (Tkinter, Qt, a web front end) | The operator UI is declared in the procedure: text inputs, checklists, images, sliders, progress. No frontend code on a station. |
| Building a sequencer | The framework runs phases in order, injects plugs, handles depends_on and multi-DUT slots. A home-made runner is the most common way to lose six months. |
| Building dashboards | FPY, Cpk, control charts, histograms and failure Pareto are in TofuPilot. A candidate who proposes a pandas notebook for yield is solving a problem you don't have. |
| LabVIEW | Useful for reading the old station during a migration, not a hiring requirement. Your LabVIEW engineer walks them through the block diagram once. |
| Advanced Python (async, metaclasses, C extensions) | A station is a folder of plain functions and plain classes. If it needs asyncio, the fixture design is the problem. |
Every plant has one home-made yield dashboard that only opens on one PC, and the person who built it is on holiday.
Self-Assessment
Use this for a candidate after the take-home, or for a current engineer planning their own move from LabVIEW. Level 2 across the board is a working station owner. Level 3 in one or two rows is a lead.
| Skill | Level 1 | Level 2 | Level 3 |
|---|---|---|---|
| Instrument I/O | Runs an existing plug and reads the value | Writes a new plug from the SCPI manual, handles termination and timeouts | Debugs a bus problem with a protocol trace, drives a multi-instrument fixture |
| Hardware exceptions | Catches the exception and logs it | Bounded retries, cleanup in close(), ERROR and FAIL reported correctly | Designs the recovery path: power cycle the fixture, re-init, resume at the right phase |
| Packaging | Runs from a venv on their own machine | Installs from requirements.txt on a station PC offline | Pins the Python version, scripts the station install, keeps a known-good image |
| Git | Commits to main | Branch, pull request, review, tag | Reviews others, bisects a regression, keeps one repo per station clean |
| Data flow | Uploads a run and finds it in TofuPilot | Declares limits in procedure.yaml, reads FPY and Cpk per procedure | Reads a drift on the control chart, ties it to a fixture or instrument, files the fix as a pull request |
A LabVIEW developer moving to Python usually scores 3 on the ideas behind instrument I/O and exceptions from day one, and 1 on packaging and Git. That's a shorter gap than most managers expect.
Two Blocks Worth Reading
Both are the size of the real thing. If a candidate can read these and say what breaks when you remove any line, they pass the first two rows of the checklist.
A plug with a timeout, a bounded retry and cleanup in close():
plugs/dmm.py26 lines
# Multimeter plug: timeout on open, bounded retry on read, cleanup in close().import pyvisaclass Multimeter: def __init__(self, address="TCPIP::192.168.1.100::INSTR", retries=3): self.rm = pyvisa.ResourceManager("@py") self.inst = self.rm.open_resource(address) self.inst.timeout = 2000 # milliseconds self.retries = retries def read_voltage(self): last_error = None for _ in range(self.retries): try: return float(self.inst.query(":MEAS:VOLT:DC?")) except pyvisa.VisaIOError as error: last_error = error raise last_error def close(self): try: self.inst.write("*RST") finally: self.inst.close() self.rm.close()The phase that uses it is two lines: def power_rails(measurements, dmm): measurements.rail_3v3 = dmm.read_voltage(). The limits don't live in the phase. They live here:
procedure.yaml25 lines
# One phase, one measurement. Limits live in the procedure, not in the code.name: PCBA Functional Testversion: 1.4.0unit: serial_number: default_value: "SN-000001" part_number: default_value: "PCBA-100"plugs: - name: dmm python: plugs.dmm:Multimetermain: - name: Power Rails python: phases.power_rails measurements: - name: rail_3v3 unit: V validators: - operator: ">=" expected_value: 3.2 - operator: "<=" expected_value: 3.4Run it with --upload and the measurement, its limits and its outcome land on the unit's run page in TofuPilot. The Cpk for rail_3v3 shows up on the procedure page once there are enough runs. Nobody writes that part.
Start With One Station
Pick the station with the highest volume, or the one only one person can open. Rebuild it in Python with the TofuPilot Framework, then run it side by side with the LabVIEW version on the same units for two weeks. The five skills above are exactly what that rebuild exercises, in order.
# Install the CLI, run a procedure locally, then run it with upload.curl -fsSL https://www.tofupilot.app/install | shtofupilot run ./procedure.yamltofupilot run ./procedure.yaml --uploadThe LabVIEW migration guide covers the rebuild step by step, and the Framework page covers the layout. The Lab tier is free, and tofupilot run works with no account.
