top of page
  • Linkedin

General Discussions

Public·2 members

SonarQube + Unity: Testing your code (Part 2)

Welcome to the second part of the Testing posts serie!

As promised, this post will cover the integration of our previous testing setup into a Gitlab CI. We'll see how to:


  • Prepare a specific Runner to ease the run and keep our CI file to a minimum.

  • Prepare the CI file to build our project, run the analysis and prepare the result.

  • Access the results on GitLab


Preparing the runner


To have the least amount of work to do in the gitalb-ci.yml, we prepare a runner equipped with the necessary tools. Here is it's dockerfile:

FROM gcc:latest
ARG SONAR_SCANNER_VERSION="7.0.2.4839"
ARG SONAR_SERVER_URL="https://next.sonarqube.com/sonarqube" 
ARG UNITY_RELEASE="2.6.1"
ARG UNITY_RELEASE_URL="https://github.com/ThrowTheSwitch/Unity/archive/refs/tags/v${UNITY_RELEASE}.zip" 
RUN apt update && apt install -y curl git gcovr cmake
RUN curl -sSLo sonar-scanner.zip "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip" \
    && unzip -o sonar-scanner.zip \
    && mv sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64 sonar-scanner \
    && rm sonar-scanner.zip
RUN curl -sSLo build-wrapper.zip "${SONAR_SERVER_URL}/static/cpp/build-wrapper-linux-x86.zip" \
    && unzip -o build-wrapper.zip \
    && mv build-wrapper-linux-x86 build-wrapper \
    && rm build-wrapper.zip
RUN curl -sSLo Unity.zip "${UNITY_RELEASE_URL}" \
    && unzip -o Unity.zip \
    && cd Unity-${UNITY_RELEASE} \
    && cmake -B build \
    && cmake --build build \
    && cmake --install build

ENV PATH="/build-wrapper:/sonar-scanner/bin:${PATH}"

It will get both sonar-scanner and build-wrapper binaries and add them to the PATH environment variable, letting us access them easily in the next step.


Registering the runner can be done following the official documentation, as it is not the focus of this post. It is just to remember to tag the runner with a tag which will be used afterward (i.e.: testing, sonar, ...). The next step will need a runner with the sonar-testing tag.


Preparing the CI file


The CI file will do the following:


  • Build our code and store the output as artifact.

  • Run the analysis using sonar-scanner.


Here is the CI file:

variables:
  SONAR_SERVER_URL: https://next.sonarqube.com/sonarqube # Replace with your SonarQube server URL
  SONAR_SCANNER_VERSION: 7.0.2.4839 # Find the latest version in the "Linux" link on this page:
                                    # https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/
  BUILD_WRAPPER_OUT_DIR: bw-output # Directory where build-wrapper output will be placed

  SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
  GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  # note that SONAR_TOKEN is transmitted to the environment through Gitlab CI

  UNITY_RELEASE_URL: https://github.com/ThrowTheSwitch/Unity/archive/refs/tags/v2.6.1.zip

build:
  stage: deploy
  tags:
    - sonar-testing
  script:
    - echo "Building the application"
    - cd app
    - cmake -B build
    - build-wrapper-linux-x86-64 --out-dir "${BUILD_WRAPPER_OUT_DIR}" cmake --build build/ --config Release
  artifacts:
    paths:
      - app/build/app
    untracked: false
    when: on_success
    access: all
  cache:
    policy: push
    key: "${CI_COMMIT_SHORT_SHA}"
    paths:
      - app/${BUILD_WRAPPER_OUT_DIR}
      - app/build/

unity-tests:
  stage: .post
  tags:
    - sonar-testing
  script:
    - echo "Running Unity unit tests"
    - cd app
    - ctest --test-dir build --output-junit junit.xml
    - gcovr -e main.c --sonarqube > coverage.xml
  artifacts:
    untracked: false
    when: always
    paths:
      - app/build/junit.xml
      - app/coverage.xml
    reports:
      junit: app/build/junit.xml
  cache:
    policy: pull-push
    key: "${CI_COMMIT_SHORT_SHA}"
    paths:
      - app/build/
      - app/coverage.xml
      - app/${BUILD_WRAPPER_OUT_DIR}

sonar-qube:
  stage: .post
  tags:
    - sonar-testing
  needs:
    - job: unity-tests
      artifacts: true
  script:
    - cd app
    - sonar-scanner
  cache:
    policy: pull
    key: "${CI_COMMIT_SHORT_SHA}"
    paths:
      - app/${BUILD_WRAPPER_OUT_DIR}
      - app/coverage.xml



It is split in three jobs:

  • Building the project and getting the build wrapper output

  • Running the Unity tests

  • Running the sonar-scanner analysis and sending it to the sonar-cloud server


Each of these job ask to use a runner having the sonar-testing tag, which will use the runner previously configured.


Accessing the results

Once you push on main, the CI will run and execute all the jobs. After a successful run, the results can be accessed on GitLab.

Here is the successful pipeline:


ree
All jobs passed!

And here is the testing results, available on Gitlab:

ree
We see that all the tests ran and no error was reported

Conclusion

This mini-serie showed the integration of only a subset of the possible frameworks available. This solution offer easy to use and setup components, already validated and widely adopted in the testing world. It shows the first steps on how to build a robust and automated test environment, which also offering rich and useful inside about your code, thanks to the Sonar-Scanner analysis.

I hope this will encourage you to try this kind of setup in your projects and that you'll build nice and bug-free code a bit more easily next time!

28 Views
bottom of page