top of page
  • Linkedin

General Discussions

Public·2 members

SonarQube + Unity: Testing your code (Part 1)

Testing your code is crucial. Having it tested automatically and reported in a concise and understandable way is a must. There are multiple aspects of testing:

- Unit tests + code coverage

- Integration tests

- Static analysis

- Dynamic analysis


In this post, we'll show you how to setup testing and analysing your code with SonarQube Cloud and Unity. It will cover:

  • Unit tests setup with Unity

  • Code coverage report gcovr

  • SonarQube Cloud report

  • CMake integration


The Part 2 will cover the integration into a GitLab CI pipeline to run the analysis and the tests on each push.


Project architecture

The project files are available as a zip:



. They are organized as follows:

.
├── CMakeLists.txt
├── main.c
├── src
│   ├── app.c
│   ├── app.h
│   ├── CMakeLists.txt
│   └── my_math
│       ├── CMakeLists.txt
│       ├── my_math.c
│       └── my_math.h
├── test
│   ├── CMakeLists.txt
│   ├── my_math_test.c
│   └── test_main.c
  • The sources are located in src/ folder

  • The tests are in the test/ folder

  • The project is configured and built using CMake. The top CMakeLists.txt is the main list file.


Building the project


cmake -B build # without tests
cmake -B build --DBUILD_TYPE=testing # with tests 
cmake --build build 

This will build the sources and our test. The -DBUILD_TYPE=testing flag is here to add the coverage option to GCC as well as adding the test/ folder to the configuration/build.

Unit tests using Unity

As stated before, we use Unity framework to write our tests. Its advantages are:

- Easy C/C++ integration

- Simple .c and .h library

- Tests are easy to write

- Concise reports

- Can be integrated with Ceedling


Running the tests

Once the sources and tests are compiled, one can run the tests using ctest:

ctest --test-dir build
Internal ctest changing into directory: /home/dtruan/posts/app/build
Test project /home/dtruan/posts/app/build
    Start 1: test_math
1/2 Test #1: test_math ........................   Passed    0.00 sec
    Start 2: test_main
2/2 Test #2: test_main ........................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =   0.01 sec

The tests run and you get a report on stdout. We'll later use a specific format to be compatible with junit report, used by GitLab CI.


Running the code coverage

The code coverage will be reported using gcovr:


gcovr -e main.c -e build 
------------------------------------------------------------------------------
                          GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
src/app.c                                      6       6   100%   
src/my_math/my_math.c                          4       4   100%   
test/test_main.c                              11      11   100%   
test/test_my_math.c                           20      20   100%   
------------------------------------------------------------------------------
TOTAL                                         41      41   100%
------------------------------------------------------------------------------

This will run the code coverage to check if our tests cover enough lines of code. We can tell it to generate the report in sonarqube format and to save it in coverage.xml:


gcovr -e main.c -e build --sonarqube > coverage.xml

SonarQube Cloud

SonarQube is a powerful static analysis and code report tool. It covers a variety of languages and offers multiple pricing plans in order to just test the tool or to support a full scale enterprise setup.


In this article, we are using the free plan and their public Cloud server. It is assumed that you already have a SonarQube account and an organization already created. You must also have your SONAR_TOKEN saved, as it will be used when running the analysis


How SonarQube works

SonarQube works in two steps:

- First it collects the build environment using a build wrapper. It generates some output files which will be used by the next step.

- Then it uses the sonar-scanner executable to analyse the code. It uses a configuration files to define the sources to analyse, the account/server information, ... It generates a SonarQube compatible report after a successful run.


The configuration file for this project is like this:

sonar.projectKey=<your_project_key>
sonar.organization=<your_project_org>
sonar.sources=src
sonar.cfamily.compile-commands=bw-output/compile_commands.json
sonar.host.url=https://sonarcloud.io
sonar.sourceEncoding=UTF-8
sonar.coverageReportPaths=coverage.xml

It specifies:

  • The project key (from SonarQube Cloud)

  • The organization this project is in

  • Where our sources are located

  • Where to look at the build command, which is the build-wrapper output

  • The sonar server URL, here we use the public server

  • The sources encoding

  • The coverage report file path (optional)


Run an analysis

Here are the steps, from a fresh state, without any build done before:


cmake -B build -DBUILD_TYPE=testing
build-wrapper-linux-x86-64 --out-dir bw-output cmake --build build
ctest --test-dir build
gcovr -e main.c --sonarqube > coverage.xml 
SONAR_TOKEN=<YOUR_TOKEN> sonar-scanner

It will build the project, run the tests and code coverage, feed them to the analysis and send the report to the SonarQube Cloud server, which can then be consulted using the Web UI:

ree

We can see the report on our main branch. Here everything passes:

  • No Security issue was found

  • Our tests cover enough of the code

Next time, we'll see how to integrate all of this into the GitLab CI to automatically run the analysis!

52 Views
bottom of page