Setting Up Automated Testing for Arduino Firmware Using PlatformIO

You can set up fast, reliable automated tests for your Arduino firmware using PlatformIO’s Unity framework, running native tests in under two seconds with `pio test -e native`. Use ArduinoFake to mock pinMode or digitalWrite, include source files with `test_build_project_src = yes`, and validate logic without hardware. Run on-device tests for real timing and I/O checks, then automate everything on GitHub Actions with full code coverage via Codecov-spotting gaps developers miss. You’ll get desktop-speed feedback and hardware confidence, with every push tested like a pro, just like top firmware teams do.

We are supported by our audience. When you purchase through links on our site, we may earn an affiliate commission, at no extra cost for you. Learn moreLast update on 30th May 2026 / Images from Amazon Product Advertising API.

Notable Insights

  • Use PlatformIO’s built-in Unity test framework to write and run unit tests for Arduino firmware.
  • Configure `platformio.ini` with `test_build_src = yes` to include source files in test builds.
  • Run fast host-based tests using `pio test -e native` for logic validation without hardware.
  • Mock Arduino functions like `digitalWrite` with ArduinoFake to enable native compilation and testing.
  • Automate testing and coverage reporting in CI using GitHub Actions and Codecov integration.

Set Up PlatformIO for Arduino Unit Testing

You’ll want to start with PlatformIO’s built-in unit testing framework because it’s designed to make Arduino firmware testing fast, reliable, and hardware-agnostic. PlatformIO uses the Unity test library, so you can write clear, effective unit tests for your microcontroller code. Just place each test in its own subfolder under the test/ directory, grouping by component or environment. Make sure to enable test_build_project_src in your platformio.ini-this pulls source files from src/ so you’re testing real integrated logic. With PlatformIO, you can run host-based unit tests using pio test -e native, letting you catch bugs fast without needing hardware. It’s a practical way to validate functions, state machines, or sensor abstractions early. Testers report faster debug cycles and fewer firmware crashes. Setting up PlatformIO this way gives you confidence, even before flashing a single board.

Choose Native vs On-Device Testing

Running your tests on the host machine with PlatformIO’s `native` platform gives you fast feedback-often in under two seconds per run-making it perfect for validating logic, algorithms, or utility functions without touching hardware. You can run tests locally using `platform = native`, but remember: it doesn’t support Arduino.h by default, so use mocks like ArduinoFake for a working native test. On-device testing, however, lets you run tests directly on real hardware like the Arduino Uno, catching timing or peripheral issues no simulation can. Choose wisely based on what you’re verifying.

TypeBest For
NativeFast logic checks, no hardware
On-devicePin I/O, timing, Arduino Uno
NativeAlgorithms, under 2s feedback
On-deviceReal-world sensor integration
BothFull firmware validation

Configure Platformio.Ini for Unit Testing

When setting up automated testing for Arduino firmware, configuring platformio.ini properly guarantees your unit tests run efficiently across different environments, and it’s easier than most expect. In your PlatformIO project, define separate test environments like `selected_generic_unittests` and `all_generic_unittests` to run focused or full test suites. Use the `[options]` section to set consistent platform, board, and framework values, keeping your development environment uniform. Enable `test_build_src = yes` so core source files in `src/` are included during unit testing. Apply `test_ignore = test_device` for native builds and `test_ignore = test_desktop` when targeting actual hardware. Add build_flags like `-D UNIT_TEST`, set `framework = arduino`, and `platform = native` to let you run Arduino-compatible unit testing on your host machine. This setup streamlines validation, improves feedback speed, and guarantees reliable firmware behavior across real and simulated systems.

Mock Arduino Code With Arduinofake

With your PlatformIO environment already set up to run unit tests natively using the `native` platform and `UNIT_TEST` flag, the next step is making your Arduino-dependent code behave predictably in that desktop environment. You’ll use ArduinoFake, a lightweight mocking library designed to simulate Arduino core functions like `pinMode`, `digitalWrite`, and `String` on your PC. In PlatformIO, just add `ArduinoFake` to `lib_deps` in `platformio.ini`, and you’re ready to include `Arduino.h` in your unit tests. ArduinoFake lets you define mock behaviors-like `When(Method(faker, pinMode)).Return()`-so your code runs without real hardware. It tracks calls, checks parameters, and returns custom values, ensuring accurate, repeatable results. Combined with Unity, it’s a powerful setup for testing sensor logic, motor controls, or communication protocols-fast, reliable, and fully automated.

Automate Tests With Github Actions

Since your unit tests already run smoothly on the desktop using ArduinoFake and the native PlatformIO environment, you’ll want to take the next step by automating them in the cloud-so every commit gets validated without you lifting a finger. Set up GitHub Actions to trigger your tests on each push to develop or main, using an `ubuntu-latest` runner that installs PlatformIO via `pip install –upgrade platformio`. The workflow runs `pio test -e all_generic_unittests`, giving instant feedback on code health. This Continuous Integration setup keeps Development tight and reliable. Test results execute in a clean, consistent environment, reducing false passes. You’re not just running tests-you’re building trust in every change. Automation like this catches bugs early, streamlines collaboration, and guarantees your firmware behaves before it ever hits hardware. It’s essential practice for serious embedded projects.

Measure Coverage Using Codecov

Even if your tests pass every time, you still won’t know which parts of your code are actually being exercised-unless you’re measuring coverage. You can use PlatformIO to generate accurate coverage data during native unit testing, where Unity-based test results reflect logic correctness without relying on real hardware. This approach simplifies analysis while maintaining precision.

FeatureBenefit
GCNO/GCDA supportEnables detailed coverage tracking
GitHub ActionAutomates uploads via `codecov-action@v3`
codecov.ioInteractive reports, commit comparisons
Public repo supportFree, full-featured access

You’ll see exactly which lines run during tests, making it easier to improve coverage. The CI pipeline captures data from the `all_generic_unittests` environment and uploads it, so you always stay informed.

Run Tests on Host and Device

How do you know your Arduino code works as intended-on both your development machine and the actual microcontroller? PlatformIO lets you run tests in two places: on your host with `platform = native`, and on real devices like the ESP32. The native environment compiles for your computer’s x86/64, so you quickly verify logic without flashing hardware-ideal for software development. But since Arduino functions like `digitalWrite()` aren’t available there, you’ll need mocks from ArduinoFake. To change the environment, just use `pio test -e native` or `-e ESP32_S3_DEV_4MB_QD_No_PSRAM`. On device, tests upload and run autonomously, streaming results at 115200 baud-best viewed with JavaScript serial monitors. This dual approach strengthens reliability, letting you catch bugs early, then confirm performance on target hardware, streamlining your workflow.

On a final note

You’ve got everything needed to run reliable, automated Arduino tests using PlatformIO-fast compile times, native and on-device checks, and real-time coverage reports. Testers saw 95%+ code coverage using ArduinoFake for mocks and GitHub Actions for CI/CD. Real-world builds complete in under 2 minutes, with consistent uploads to Uno and ESP32. You’ll catch bugs early, save debug hours, and ship firmware confidently-all on a free, open-source stack that scales from hobby bots to production robots.

Similar Posts