One of the most widely accepted and used software engineering practices.to test the proper functioning of individual blocks of code is the unit test.
This is especially true for embedded IoT devices. The time necessary for development of solid unit tests is often not spent because the interface with the hardware side is more difficult to create compared to devices that are only software.
In the case of Zerynth, this is not true. Zerynth has developed an automated test workbench that allows new versions to be released and tested quickly and reliably.
One of the most used and accepted software engineering practices is to write and use unit tests, or single subunits of code to ensure that each of them has the expected behavior in each of its possible use cases.
Generally, these are automated practices that allow with the only investment of time, for the drafting of the required tests. This greatly improves the quality of the code and can find any anomalous behavior during the tests, which speeds up release times in case the tests are used.
The need for solid and error-free code is particularly important with embedded devices, as these, unlike software-only solutions that can be easily updated with new releases, can be difficult to update or even difficult to reach once they are installed. For this reason, it is imperative to develop suitable and specific test units for each embedded device
Unfortunately, this is rare, because testing an embedded device requires more time and resources than a simple software or a web-app program. In particular, embedded unit tests may require the construction of a test setup, specific to each unit, and may need to be adapted to different types of devices.
It goes without saying that having to test hundreds of functions on an entire array of different devices, building a suitable setup and making sure that this does not present systematic or systemic errors, is not a simple undertaking. This all requires considerable time investment and resources, which is why so many embedded developers choose not to develop and maintain a physical test workbench.
Nevertheless, the Zerynth IoT platform has been developed in such a way that all the resources invested in developing embedded unit tests are essential to ensure that our users have a refined and reliable product. For this reason, the test pipeline requires that all code units with new features to be implemented are first tested with all the boards mounted on the workbench (db zm1, 4zerobox etc) and then released, if they pass the test, further to each of our devices. .
The Zerynth test pipeline
The release of low-level code and libraries in Zerynth follows this process:
- code development;
- writing of the relative unit test;
- launching the automatic chain of unit tests;
- debug in case anomalous behaviors emerge;
- Repeat from point 3);
- release a new version of the SDK
Figure 1 Zerynth test pipeline
The Zerynth workbench supports various types of tests.
Rapid unit tests. These tests are launched before each release. They check the behavior of each unit of code, report anomalous behavior which will then be corrected before the release. These tests are automatically launched on every supported card by testing every available library, and they are updated periodically to ensure full test coverage. Once launched, the tests run autonomously, until the final output results are reached. This type of unit test includes all those that cover the drivers of the various peripherals (ADC, I2C, SPI, USART …) and sensors.
Stability unit test. These tests operate continuously and attempt to verify the stability of the codebase over time. The stability tests publish their status in the cloud to allow us to track any errors that would be difficult to identify on unit tests with a limited duration. These include, for example, data log tests on flash memory which verifies cases of possible memory corruption that can occur after many read and write cycles. Another case study concerns connectivity stability tests and sending data to the cloud that is carried out in conjunction with a network jammer to simulate critical network conditions.
FOTA. Finally, reliability tests of the FOTA are carried out before each release, to ensure that, for each device, the firmware can always be updated at each release.
Figure 2. Rapid benchmark and stability tests
Figure 3. Benchmark stability test
The investment in the development of unit tests, despite the difficulties of dealing with embedded systems, bears fruit, thus allowing Zerynth to test the code in a complete, rapid and continuous manner in order to release new and solid embedded features quickly.
A practical example of a unit test
Figure 4. Example of Unit Test for gpio
In conclusion, Figure 4 shows us a simple example of a unit test to test the correct functioning of interrupt callbacks designed for the ZM1-DB and 4ZeroBox-Mobile boards.
The test uses the first pin on the board to trigger a callback initiated on a second pin. This callback sends an output to the workbench, which compares the output with the expected one to determine the test result.
- Lines 10-13: initialization of the output pin
- Line 16: callback definition
- Lines 20-21: initial initialization of the input pin to which we associate the callback
- Lines 22-24: The output pin is moved to trigger the test callback.
To find out all the features supported and tested on our IoT devices, link to the documentation.