Testing Zephyr Firmware

A feature that builds has cleared the lowest bar there is — it's valid C. Whether it's correct is a different question entirely, and on firmware the wrong answer rarely shows up in a tidy log line. It shows up as a dead device on someone's desk, three steps into a flow nobody re-checked by hand.
A test is how you catch that at your desk instead — where the fix costs a coffee break, not a truck roll.
And here's the part that kills every excuse: you don't need hardware. Everything in this section runs on native_sim — your test compiles to an ordinary Linux program and finishes in milliseconds.
Why it's worth it
- Firmware bugs are expensive. A web bug ships a hotfix in minutes. A firmware bug ships a technician to a site.
- You can't re-check by hand. Dozens of releases, hundreds of features. "Did I break anything?" should take seconds, not a weekend of clicking.
- Tests make you faster. Sounds backwards; isn't. A green suite lets you refactor fearlessly. Without one you tiptoe — and tiptoeing is slow.
In automotive, medical, and aerospace you literally cannot ship without test evidence (ISO 26262, IEC 62304, DO-178C). The report is the paperwork.
Two ways to test
Zephyr gives you two complementary approaches. Same runner (Twister), same native_sim, very different reach:
| ztest | pytest harness | |
|---|---|---|
| You write the test in | C, compiled into the firmware | Python, running on your PC |
| It can see | functions, variables, internal state | only what the device exposes — shell, serial, network |
| Perfect for | unit-testing logic and functions | interaction & system tests (shell, OTA, networking) |
One line to remember: testing a function → ztest. Testing a behaviour → pytest.
Your path
We'll carry one tiny example the whole way — an add() function — and test it both ways, so each step builds on the last instead of starting over.
- How Zephyr testing works — the mental model: two tools, one dead-simple contract between them. Read this first and everything after it becomes obvious.
- Write & run your first test — the hands-on ztest: four files, three macros, watch it pass and fail on purpose.
- Testing from the outside: pytest — when an in-firmware assert simply can't reach, drive the device from Python instead.
Prerequisites
- Comfortable building and flashing with
west— see Zephyr Basic - A working Zephyr environment (
native_simruns on your host, so no board needed)
Short on time? The first two pages have you writing real, running tests in about ten minutes. Come to pytest the moment you hit something you can only observe from outside the firmware.