What makes unit tests great? They ensure that functions or components work as intended.
Unit tests are also very simple to use. This is because you can focus on a single piece of code – and isolate all dependencies through Stubs and Mocks.
This combination of simplicity and powerful capabilities make them a joy to use.

Unit tests can check hardware-specific code!

You can test hardware-specific code with unit tests. Assume your production code is running on a microcontroller that provides chip functionality to calculate a CRC. You can write a software component that uses this functionality through special function registers.
Can you write a unit test for this component? Fortunately, yes!
You must only keep in mind that the test will not run on your developer machine anymore – because there is a hardware dependency to your specific chip. But compiling both code and test for the chip and running it there is possible. This approach is called on-target testing.

Unit tests can not test pin behavior… right?

But what about code that does something on the chip pins? Like toggling a GPIO pin, sending a CAN frame or receiving data through a UART?
The underlying hardware is very powerful today – and thus also complex. A typical reference manual for a microcontroller runs in to thousands of pages. Seasoned software developers know that this complexity introduces much room for bugs.

So it would be great to test a combination of code and pin behavior. Traditional unit tests cannot do that. For it to work, we would need a way to use Mocks and Stubs that work on the pin level. And this is precisely what we introduced with our ExecutionPlatform and its Endpoints.

Endpoints provide test capabilities for pin behavior

What we call Endpoint is the interface between test and periphery.
There is a specific endpoint for each periphery type. For example a GPIO Endpoint, a CAN Endpoint and a UART Endpoint.
With these Endpoints, you can read the state of a pin, receive and inspect CAN frames and send data through a UART.

From a test perspective, we isolate the microcontroller and provide you with an interface to write tests against this pin behavior.
In traditional unit testing you write your test in the same programming language as the code-under-test. And you compile it together to a single executable.

Because the pin behavior is external to the code-under-test, their test sequences are separated from your code.
So each test consists of code running on the microcontroller – and a test sequence (written in RobotFramework) running on a PC. We call this approach Open Loop Testing.

Here are a few examples how this combination between code and test look like in practice:

  • Read pin state with GPIO Endpoint, call driver code for pin toggling in code, read pin state again and assert that it changed.
  • Call driver code that sends can frame, read received frame with CAN Endpoint and assert frame detail like id and data.
  • Send data through the UART endpoint, call driver code and assert that the data was received on the microcontroller.

Learn more

Our goal is that you can test your driver code in a way that is both simple to use and yet powerful enough to cover all corner cases.
The best way to understand the enormous potential of Open Loop Testing is to try real world examples.
You can use our browser-based demo and run the first example in the next few minutes. The demo is connected to ExecutionPlatform hardware and therefore provides you with a realistic view.