

Natalia Pluta
Mastering Zephyr RTOS Testing: Getting Started with Twister
Friday, February 27, 2026
Introduction
In the world of embedded systems, manual testing is often the bottleneck that slows down innovation. As projects grow in complexity - supporting multiple architectures and hardware configurations - ensuring stability becomes an uphill battle. This is where Twister comes in.
Twister is not just a script; it is the backbone of the Zephyr Project’s quality assurance. Whether you are validating a simple driver or a complex multi-threaded application, Twister provides a scalable, automated way to ensure your code works across the vast ecosystem of Zephyr-supported boards. In this guide, we will move beyond manual compilation and show you how to leverage Twister to streamline your testing workflow from day one.
Author's Note: This article was written with the support of Zephyr 4.3.0 (Source: GitHub v4.3.0, Documentation). However, it is highly probable that the concepts and commands will work perfectly fine with older and newer versions of the RTOS.
Building and Running Your First Zephyr Tests with Twister
Welcome to the first part of our Mastering Zephyr RTOS Testing series. Before writing any custom C code or integration scripts, you need to understand the beating heart of Zephyr's testing ecosystem: Twister.
Prerequisites: Before diving in, we assume you already have a functional Zephyr workspace set up. If you haven't done this yet, please follow the Zephyr 4.3.0 Getting Started Guide.
What is Twister?
Twister is Zephyr's integrated test execution framework that discovers, builds, and executes tests across multiple platforms. Think of it as your single entry point for running any kind of Zephyr test. Instead of manually compiling binaries and flashing them to a board to see if a feature works, Twister automates the entire pipeline.
How Twister Works Under the Hood
When you invoke Twister, it orchestrates a comprehensive end-to-end execution pipeline:
Discovery - scans directories for
testcase.yamlorsample.yamlfiles.Filtering - applies platform, architecture, tag, and filter-expression constraints.
Building - compiles each test scenario for each matching platform (in parallel).
Execution - runs the binary on the target (simulators, real HW, etc.).
Evaluating - uses the configured harness to parse output and determine pass/fail.
Reporting - generates JSON, JUnit XML, and optional coverage reports.
For a full architectural reference, you can check the Twister Documentation.
The Anatomy of a Test: testcase.yaml and sample.yaml
Before you can run a test, Twister needs to know it exists. Twister discovers tests by recursively scanning your directories for testcase.yaml or sample.yaml files.
The testcase.yaml File
The testcase.yaml file defines test scenarios and their configuration. Here is an overview of some of the available options:
Note: While
ztestis the default C testing framework, we will explore other harnesses likepytest,console, androbotin subsequent articles.
The sample.yaml File
While testcase.yaml is used for formal test suites, Zephyr uses sample.yaml to build and verify application samples. Its structure is very similar to a test case, often relying on the console harness to match simple text output to verify the sample built and ran correctly:
Filter Expressions
Within both of your YAML files, you can define filter expressions that enable conditional test execution based on Kconfig, devicetree, and the environment. This ensures tests only run on boards that actually support the required hardware features or architectures:
Virtual Test Platforms: native_sim vs unit_testing
You don't need physical hardware to start testing in Zephyr. In fact, most of your day-to-day testing should be done on your host machine. Zephyr provides two primary virtual platforms for this, and it is crucial to understand the difference between them:
native_sim: Recommended for most unit and integration tests. It provides the full Zephyr OS, so modules that use logging, drivers, or other OS features work correctly. You can mock only the specific dependencies you want to isolate.unit_testing: Used only for pure utility functions with zero OS dependencies (e.g., CRC calculation, string parsing). This board provides a minimal POSIX environment without the Zephyr kernel.
For a deeper dive into configuring tests specifically for this minimal environment (
unit_testing), check out the Zephyr Unit Testing Quick Start Guide.
Running Your First Zephyr Tests
Let's run some real tests using Zephyr's built-in kernel test suite. To avoid compiling the entire OS (which would take a very long time!), we will narrow our command down to just the threading subsystem.
Testing on native_sim
To build and run tests that require the full Zephyr OS (like the threading subsystem), we use the native_sim board. Execute the following command from your Zephyr repository root:
You should see an output similar to this, detailing the build progress, filtered tests, and final pass rates:
Testing on unit_testing
If you want to run tests strictly on the minimal POSIX board to validate pure utilities, you can utilize the unit_testing board. Tests dedicated to this platform are gathered under the tests/unit/ directory in Zephyr. For example, you can execute the following command to test the CRC utility functions:
The output is often much faster since it doesn't need to compile the full RTOS:
Controlling Twister Execution
Twister provides immense command-line flexibility for managing platforms, filters, builds, and outputs.
Tip: The commands below use
-T tests/kernel/threads/as a safe, fast example. You can replace this path with your own application's test directory.
Platform Selection
You can target one or multiple platforms, or filter by architecture:
Test Selection and Filtering
Twister lets you narrow things down by tags or patterns:
Build Control
Sometimes you only want to verify the code compiles without executing it:
Output and Reporting
Twister's reporting is highly customizable:
Parallel Execution
When running tests in Continuous Integration (CI), speed and reliability are key:
Executing tests on real hardware
Simulators are fantastic, but eventually, you need to prove your code works on real hardware. Twister allows you to target physical hardware by specifying a custom flash command or passing device-testing flags.
For example, to test the built-in hello_world sample on a physical Nordic nRF52840 Development Kit, use the following command:
Note: You can easily replace
nrf52840dk/nrf52840with the board identifier for your hardware. You can check available boards by runningwest boardsor via the interactive searcher in the Zephyr 4.3.0 Board Documentation.
Because this command targets real hardware, Twister will provide a Hardware distribution summary showing exactly which physical boards passed or failed:
Conclusion
Mastering Twister is the first step toward professional-grade Zephyr development. By moving away from manual "flash-and-hope" debugging and toward automated test suites, you ensure that your code remains robust even as the underlying RTOS evolves.
In this guide, we've covered how Twister discovers tests, the difference between virtual platforms, and how to execute tests on both simulators and real hardware. See you in the next guide!