Uncannier Software

It's not enough to just be uncanny

Unit Testing of Embedded Firmware – Part 5 – Continuous Integration (CircleCI)

Don’t be sad, but this is the final episode of a series that started here: https://uncannier.com/unit-testing-of-embedded-firmware-part-1-software-confucius/

This article is all easy and all gravy: supporting Test Driven Development (TDD) by getting embedded firmware unit tests running on a continuous integration server.

As per the rest of this series, the Uncannier Thunderboard projects will be the example. Thus CircleCI will be the continuous integration platform. The unit tests make use of the CppUTest harness, and are x86 unit tests running in the cloud, inside the Uncannier Thunderboard Docker container.

Although I use CppUTest as the example, this should be easily adaptable to pretty much any harness: CppUnit, Unity, Google Test, whatever.

Docker Image

The Uncannier Thunderboard Docker image has been modified to add all of the tools needed to build the Test build configuration, execute the unit tests, and generate an LCOV coverage report. If you have read the other parts of this series, these additions are unsurprising.

Dockerfile changes: https://github.com/gregbreen/uncannier-thunderboard-docker/commit/78d6234eb8ded448d6c257a7b6ec9f1768c867d8#diff-3254677a7917c6c01f55212f86c57fbf

# Packages needed for unit testing
RUN apt-get install -y make
RUN apt-get install -y gcc
RUN apt-get install -y g++
RUN apt-get install -y gcc-multilib g++-multilib
RUN apt-get install -y libcpputest-dev:i386
RUN apt-get install -y lcov

CircleCI Configuration

In this section I detail the CircleCI config.yml changes for the Uncannier Thunderboard Sense 2 project. The changes for the Uncannier Thunderboard React project are essentially identical.

Sense 2 config.yml changes: https://github.com/gregbreen/uncannier-thunderboard-sense2/commit/00fd721f2e929e8d907733e64d177f4238a18444#diff-1d37e48f9ceff6d8030570cd36286a61

React config.yml changes: https://github.com/gregbreen/uncannier-thunderboard-react/commit/fbf830f54b0d4e9d72cf9a8146503ca4fe762089#diff-1d37e48f9ceff6d8030570cd36286a61

Build The Test Configuration

Obviously the Test build configuration has to be built to produce the unit test executable. Due to the post-build step introduced in the previous article, this will also produce the LCOV coverage report.

- run:
    name: Build the Uncannier Thunderboard Sense 2 application - Test configuration
    command: /opt/SimplicityStudio_v4/studio -nosplash -application org.eclipse.cdt.managedbuilder.core.headlessbuild --launcher.suppressErrors -import uts-application -cleanBuild uts-application/Test

JUnit Output

JUnit output is a defacto standard supported by pretty much every CI tool and test harness, allowing the CI tools to parse test results. A run step has been added to run the unit test executable again, but this time produce JUnit output.

- run:
    name: Generate xUnit-compatible test output
    command: mkdir -p JUnit; uts-application/Test/uts-application -ojunit; mv cpputest*.xml JUnit

Store Test Results

The following step tells CircleCI to parse and store the JUnit-compatible test output.

- store_test_results:
    path: ./JUnit

This results in CircleCI reporting test summaries for each build.

Store Code Coverage Report

CircleCI can also be told to store the code coverage report as an artifact.

- store_artifacts:
    path: ./uts-application/Test/Coverage
    destination: Coverage

And the LCOV code coverage report is directly accessible in the cloud: https://12-155989753-gh.circle-artifacts.com/0/Coverage/index.html


Once you’ve done the hard yards of getting TDD and unit testing happening on your development machine, it’s quite trivial to get it happening in your CI tool. Like I said, gravy.

Uncannier Pull Requests

Uncannier Builds


Tagged , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *