Embedded Software Testing: A Practical Guide
Testing strategies for firmware and embedded systems where traditional approaches don't apply. Perth, Melbourne, Sydney and Brisbane.
Testing strategies for firmware and embedded systems where traditional approaches don't apply. Perth, Melbourne, Sydney and Brisbane.
Embedded systems break most of the assumptions that normal software testing relies on. There's often no screen, no keyboard, no debugger you can just attach. The code runs on specific hardware that behaves differently to your development machine. Updates after deployment may be expensive, difficult, or flat-out impossible. And when bugs escape into production, the consequences aren't just a crash. They can cause physical damage or safety incidents.
The specific challenges:
Test individual functions in isolation, typically on your development PC rather than the target hardware. The trick is abstracting hardware dependencies so pure logic can be tested without physical devices.
Tests how software components work together. You might still mock the hardware, but the focus is on real interactions between modules: does the sensor processing module correctly feed the control algorithm, which correctly drives the output stage?
This is where things get interesting. The real firmware runs on real target hardware, but the external world is simulated. The device under test connects to a simulator that pretends to be the sensors, actuators, and communication partners.
The complete system tested in a real or realistic environment. For a motor controller, that means an actual motor. For a weather station, that means a temperature chamber. For an industrial safety system, that means simulated fault conditions with real response verification.
Software simulators model the target processor and its peripherals. QEMU handles some architectures well; most chip vendors provide their own simulators; or you build a custom simulation environment that models your specific hardware.
Simulation advantages: Test before hardware arrives. Run faster than real-time. Inject faults and edge cases trivially. Parallelise test execution across multiple virtual devices. CI/CD friendly.
Analyses code without executing it. Finds bugs that testing might miss entirely: uninitialised variables, buffer overflows, null pointer dereferences, unreachable code. For safety-critical systems, static analysis isn't optional.
Measures which code paths your tests actually exercise. For safety-critical systems, standards like DO-178C and IEC 62304 may require 100% statement and branch coverage. Even for non-critical systems, coverage analysis reveals the code you haven't tested, and untested code is where bugs hide.
Deliberately causing failures to verify error handling. Simulate sensor failures, corrupt communication packets, interrupt power during flash writes. This is how you find out whether your error handling actually works, rather than assuming it does because the happy path tests pass.
Medical devices, automotive ECUs, aerospace flight systems, and industrial safety controllers don't just need thorough testing. They need documented, traceable, auditable testing that meets specific regulatory standards.
Every requirement traces forward to test cases that verify it. Every test case traces back to requirements it validates. If there's a gap in either direction, something isn't covered. Regulators check this.
Standards define minimum coverage levels depending on the safety classification:
Test plans, test procedures, test results, and traceability matrices need to be documented and audit-ready. Good automation generates this documentation as a byproduct of the test process. You shouldn't be writing test reports by hand.
Manual testing doesn't scale. With embedded systems that may run for years in the field, you need automated regression testing that catches new bugs every time the code changes.
Automated HIL rigs can run hundreds of test cases without human intervention. The upfront investment is significant: dedicated hardware, custom test fixtures, and test scripting infrastructure. But for any product that will be maintained over years, the payback is clear.
Cost trade-off: A HIL test system can cost tens of thousands (or more). But manual testing of complex embedded systems costs more in engineering time, slower release cycles, and escaped bugs that reach customers.
Depends on the product. For a simple sensor node, probably not. Simulation and on-target manual testing may be sufficient. For anything with safety implications, complex real-time behaviour, or a long production life, HIL testing pays for itself quickly.
Unity is lightweight and widely used in the embedded community. CppUTest works well if your team is comfortable with C++. Google Test is powerful but heavier. For most embedded projects, Unity is a solid default choice.
Unit tests on a PC won't catch timing issues because the execution model is completely different. You need either HIL testing on real hardware or a cycle-accurate simulator. Instrument the code with timestamping, use a logic analyser or oscilloscope to verify timing at the hardware level, and test under realistic load conditions.
Comparing FreeRTOS, Zephyr, VxWorks and other real-time operating systems.
OTA and manual update approaches for deployed embedded devices.
Securing connected devices from design through deployment.
Ask the author
Ask it here and it comes straight to the founder. No sales call, no obligation, and a real answer even if the answer is that you do not need us.
Kasun Wijayamanna
Founder, replies within one business day
Tell us what you're working on. We'll come back with a practical recommendation and clear next steps.
Built here. Your data stays here.
Thanks for reaching out. We will get back to you within one business day.
See what else we do