Why using test automation and continuous integration in your nRF52 project?

Working on an nRF52 MCU project? Looking to connect your source code with test automation? This post will detail how to create an nRF52 continuous integration that automatically compiles and test your nRF52 project every time new code is pushed to your repository. On top of it, every time a code push breaks your tests, you’ll get a notification.

Read how to shorten embedded software R&D time with continuous integration.

This is just one of the steps towards a full nRF52 continuous integration for embedded software. We’ll be discussing test automation in the next series of posts.

A working demo of nRF52 continuous integration and test automation

Let’s start with the following working demo. Checkout this GitHub repo. The demo firmware is created using the mBed CLI and targets the nRF52_DK board with the nRF52832 MCU. Makefiles projects are good for nRF52 continuous integration because it’s easy to setup an automatic build server for them. By the way, Makefile is just one option. Checkout the following post for more.

The sample is connected to CircleCI and Travis CI. Both tools offer free versions that are satisfactory when you’re working on small projects (take a look at this comparison on continuous integration tools for embedded software). When you want your code to be closed source, there’s a paid option for that. We’re using Git as we think it’s perfect for embedded software (check out this link).

The demo application is a simple debouncer logic code. The test requires you to trigger button presses in precise timing to test the debouncer thresholds. This is a great example of how using simulation and emulation is super useful. Using the Jumper emulator is perfect for this nRF52 test automation case.

Why using a simulator/emulator for nRF52 test automation is valuable

In this example, we are using the Jumper Virtual Lab to help us run our tests. Jumper offers a fast and easy way to trigger buttons, GPIOs and other sensors on the board. For example think about the hassle and flakiness you’ll suffer when testing a button press automatically on a hardware device in a physical lab. You’d have to create a test harness or use a robotic arm just to press the button. Using jumper we can run the device for an accurate, consistent amount of time and make sure the button is being pressed precisely when we want it to.

Another advantage is that it is easy to connect Jumper to a continuous integration service, as you’re about to witness.

Let’s build our nRF52 continuous integration process in 3 steps

Step 1 – creating an nRF52 test automation Jumper Test Script

First, let’s write a test script for the debouncer. The sample turns a led on every time the button is pushed. It also uses a simple debounce logic to make sure that after the button GPIO interrupt occurred, the rest will be ignored for 300 ms.

We’ll create a test.py file with that will contain the test code. I’m going to use Pythons unittest module as a testing framework. We’ll first add our imports:

Next, we’ll add a function that will track GPIO changes to count the number of times the LED was turned on (in a physical lab you’ll need to wire-up a logic to the board and connect it to a dedicated computer). If the debouncer worked, we expect this number to be 1 by the end of the test.

We’ll turn the button on and off 3 times. We’ll then let the simulation run for 280 ms and then assert the number of times the led was turned on. On real hardware we should have use a robotic arm or wire-up signal generator to that button pins.

Step 2 – run the automated test locally

To make things easy, we created a docker container that has the tool chain preinstalled. It’s going to be helpful in the CI tools. Follow the next steps:

  1. Install Docker (if you’re looking to implement an nRF52 continuous integration process, Docker is one of the building blocks you’ll need).
  2. Run

Results will include ‘Ran 1 test in 6.213s’. Congratulations. It means you just ran your first test on the Jumper Virtual Lab.

Step 3 – connect it to a continuous integration service

I chose 2 commonly used services to implement the test automation server. The value from these services is huge. From the moment you connect the service to your code, you’ll get email notifications whenever the build breaks.

Building continuous integration using CircleCI

Let’s start with CircleCI. I recommend logging in with your GitHub account as it’ll automatically connect to your projects. From there, hit Add Projects button on the left, search the project you wish toset up:nrf52 continuous integration circleci

Now click on ‘Set Up Project’. Choose Linux as the operating system and follow the Next Steps instruction in the bottom.

nrf52 continuous integration circleci configuration Circle uses a config.yml file that should be located under your project root-folder/.circleci. Once that file is present in your repo, you can hit the ‘Start Building’ button (the config.yml and .circleci folder are already located in the repo you’ve forked so you can go to step 5 and hit ‘Start Building’). Here’s the config file I’m using in the demo project:

I chose our own custom docker image as the default CircleCI container does not include the ARM-GCC compiler (not a huge surprise :)). Circle CI automatically checks out your project, and will then hit the command ‘make’ as the config file depicts. We’ll then store the artifacts created in the build folder. And that it! Once you hit ‘Start Building’, a build task will be generated. If it worked locally using Docker, there’s no reason it should not work in the continuous integration server. Checkout the resulting dashboard in this link.

CircleCI STM32 continuous integration success

Building continuous integration using Travis CI

Let me demonstrate another useful continuous integration tool – Travis CI. Travis is highly useful, though it doesn’t provide as many built in capabilities like Circle CI. For example, artifacts management is only available through Amazon S3 uploading and performance tends to be slower. Log in to Travis-CI and hit the + button to add a project.

travis CI STM32 continuous integration project setup

If you’re connected your GitHub account, it’ll find your project. Just search for it and toggle the widget on the right to the on state. Travis works with a .travis.yml file located in the root folder of your repo. In this sample I used the same container to build the project:

And it works too! Here’s a link to the dashboard.

Travis-ci STM32 continuous integration success

Run the continuous integration demo it yourself

If you want to take it for a spin yourself, just used the fork of the sample repo and connect it to CircleCI or Travis-CI. Then, change the code locally and push it to GitHub. You’ll see how the continuous integration services pick up the build task and send you a notification if something broke.

Issue test automatically after each software build

Looking to learn how to connect test automation to run right after each build? Check out our latest post on test automation for embedded software.

Next steps

If you’d like to build continuous integration process for your own embedded software project, open free account of Jumper Virtual Lab and go through the documentation.