Article summary
Setting up a comprehensive test suite for your embedded project is crucial to its success. Embedded issues are notoriously tricky to debug, and having a test suite complete with unit and integration tests will aid massively in fixing bugs that arise.
Fortunately, Ceedling provides a framework for developing embedded projects with C, and it comes with everything you need to get automated tests up and running. This guide will run you through the steps to get CircleCI setup with Ceedling.
Creating your CircleCI Config
The first step is to create your CircleCI config file. This is the file that Circle reads to understand how to run your test suite. If you’ve never worked with Circle before, it would be helpful to go through this guide to make sure your configuration is good to go.
Let’s begin by creating a job. We’ll just call it build
:
version: 2
jobs:
build:
docker:
- image: circleci/ruby:2.4.2-stretch
steps:
- checkout
So far, all we’re doing is telling Circle to spin up a container with Ruby on it, and to checkout our code (the checkout
command is built into Circle). Let’s add some actual functionality. Underneath checkout
, add this code:
- run:
name: Installing Bundler
command: gem install bundler
- run:
name: Installing Ruby Gems
command: bundle install && bundle clean
Since Ceedling is built with Ruby and uses Bundler to run tasks, we need to make sure those are installed on our container. Now that we have all of our dependencies, we can actually start running some tests. Add this code to your config file:
- run:
name: Running Unit Tests
command: bundle exec rake test:all
This is telling Circle to run the test:all
command using Rake, a task runner that was installed earlier as a Ruby Gem. If your project doesn’t use Rake, then you can replace it with ceedling
. The test:all
command comes built in with Ceedling, and it will run your entire suite.
Continued Improvements
After wiring up your CircleCI config and your Ceedling project file, you should be able to see your test suite run whenever you push new changes! If you’re having issues or your tests aren’t appearing on the UI, make sure that you’ve followed all the steps in this guide about linking Circle up to your version control remote host.
Now let’s take a look at some of the other valuable features you can take advantage of with CircleCI. Here’s how you can set up some of most important ones.
Build a release artifact
It’s often desirous for a CI system to create a release artifact that can be distributed or deployed. The same is true for an embedded project: You might want an .axf
or a .hex
file, for example, to be generated once your tests have run. This is easy to do with Circle. Just add this code to the end of your configuration file:
- run:
name: Building Release Artifact
command: bundle exec rake release
Similar to test:all
, the release
command is built into Ceedling, and it will generate a release executable. Now that we have it built, though, we need to find a way to access it. Circle allows you to do this by adding a store_artifacts
step, which takes a path to a directory or file to be stored at the conclusion of your test run. You’ll want to include this code after your build step:
- store_artifacts:
path: build/artifacts/release
This will allow you to access your build artifacts under the “Artifacts” tab on the Circle UI when your tests run. You might need to adjust the path if you’ve defined a custom build directory, rather than Ceedling’s default.
Store and display test results
Storing a release artifact is important, but what if you also want toalso store your test results for later retrieval? Doing so has the added benefit of allowing integration with CircleCI’s Test Summary feature, and, if your plan supports it, Insights. The tricky thing here is that Circle can only parse test results written in JUnit XML format, which Ceedling doesn’t output by default. Fortunately, Ceedling comes with a built-in JUnit formatter plugin. Simply add it your project.yml
file like this:
:plugins:
:enabled:
- junit_tests_report
Now that we’re outputting test results in the correct format, we just need to tell Circle where to find those results. By default, they’ll be stored in the build/artifacts/test
directory, so we can add this code to our Circle config file. (For best results, put this step directly after your tests run, and before doing a release build.)
- store_test_results:
path: build/artifacts/test
That’s all there is to it! Circle should now display your test summary at the top of each job. Note that this won’t store the actual output XML files as artifacts, but you can easily do that by adding another store_artifacts
step with the same path as above.
Run multiple test suites
One final trick you can do with Ceedling and Circle is to break up your tests. Previously, we were just using the test:all
command, but let’s say you have multiple groups of tests that you want to run as separate test suites. (For example, you might want to run your unit and integration tests separately.) It’s easy to do this since Ceedling allows you to run tests using a test:path[insert/your/path/here]
command. Simply add this code:
- run:
name: Running Unit Tests
command: bundle exec rake test:path[unit]
- run:
name: Running Integration Tests
command: bundle exec rake test:path[integration]
when: always
Notice that now, rather than just running test:all
, we’re running both our unit and integration test suites as separate commands. Also note the when:always
line that we’ve added. The reason we included this is that Circle will cancel all of your remaining run
commands as soon as the first one fails. In our case, we want to run our integration tests even when we have unit test failures, so we specify the when:always
.
That should get you up and running with an automated test suite that can help keep your code bug-free and create release builds without any extra work on your part. Feel free to share in the comments any other helpful tricks you’ve found for setting up a CI system on an embedded project!