Automation and functional tests
Unreal ships an automated testing framework that runs inside the engine itself — no external test
Unreal ships an automated testing framework that runs inside the engine itself — no external test
Boost.Test is a unit testing framework for C++ that provides test case definition, rich
Automating the path from a commit to a deployed model, with gates that can actually stop a bad one — not automation for its own sake, but a system where "commit" doesn't mean "deployed," and a real evaluation gate stands between the two.
What is CTest?
Google Test (GTest) is Google's C++ testing framework. Tests are plain functions wrapped in macros; GTest collects them automatically and reports failures with file name, line number, and the expected vs. actual values.
Unit Testing Firmware drew a clean line around the logic that needs nothing from the hardware at all — a parser, a state machine, a checksum — and pointed at this page for the harder case: logic whose whole job is to talk to a peripheral. A driver cannot be tested by giving it inputs and checking outputs the way a parser can, because its inputs and outputs are register writes and register reads, and there is no register to read from on a laptop. Testing it on the host requires something on the other end of the bus that behaves like the real device without being it.
One aggregate number hides every failure that matters. A model at 94% accuracy can be failing badly on a 5% subgroup, systematically wrong in a specific, predictable direction, or actively worse than the model it's replacing on the exact cases that matter most — none of which a single headline metric will ever reveal.
Every technique in the rest of this folder needs a board on the desk, or at minimum a physical binary running somewhere real. Unit Testing Firmware and Mocking Hardware sidestep that by pulling logic out from behind a seam and running it on the host — a deliberate, narrow substitute for one driver's register interface. Simulation is a different move entirely: instead of extracting the logic, it models the chip, and runs the actual, unmodified cross-compiled firmware.elf against that model — the same instruction stream, the same startup code, the same register pokes, executing against a virtual STM32 instead of a real one.
There is a tool that finds real defects, requires no new install, no configuration file, and no CI integration beyond a flag already accepted by the compiler you are already invoking on every build — and most projects run it in a mode that throws its findings away. That tool is the compiler itself. arm-none-eabi-gcc already builds a fully type-checked internal representation of your program to generate code from; a warning is analysis it already did, offered back to you, and the default build configuration in a great many embedded projects is -Wall at best, or nothing at all, which means the cheapest static analysis available is routinely left switched off.
Test integration in CMake involves structuring your project to support different types of tests (unit, integration, system), managing test dependencies, and creating a smooth testing workflow. This goes beyond basic CTest usage to build a comprehensive testing strategy.
Test Doubles Taxonomy
The ordinary embedded development loop is: change a line, build, flash, power-cycle or reset, and watch a UART or an LED to see whether the change did what you meant. On a fast board with a fast probe that loop is a few seconds; on a slow one, or one shared with a bench full of other work, it is tens of seconds, and every one of those seconds is spent re-verifying code paths that had nothing to do with the line you just changed. A state machine with a dozen transitions and a handful of edge cases does not get thoroughly exercised at that cadence — it gets exercised until the one case someone thought to try passes, and the rest ride along untested until a customer finds them.