Color Mode


    Language

Code Coverage with SonarQube and Bitrise for Swift

July 22, 2022

At Monstarlab, we are using SonarQube to gather metrics about the quality of our code. One of the metrics we were interested in is code coverage. However, just running sonar-scanner on the project will not upload the coverage data to our instance of SonarQube. Here's how we got code coverage reports on SonarQube with Bitrise, our favourite CI/CD service.

Getting started

Our apps are already set up on Bitrise, and we had already set up SonarQube to run on every pull request. What we want now is to also gather code coverage data and send them to SonarQube.

First of all, we need to gather the code coverage data from Xcode. We do that by editing the Test scheme action in Xcode:

  • Open your project in Xcode
  • Go to Product > Scheme > Edit Scheme (or CMD + <, or option + click on the target, next to the simulator in the top bar)
  • Select the Test scheme action
  • In the Options tab, make sure the checkmark next to Code Coverage is selected Make sure this change is committed to git when you start testing your updated Bitrise workflow.

Running the tests and getting the coverage data

Let's have Bitrise run the tests so it can then gather the coverage data. We are editing our pull-request workflow on Bitrise and adding the step "Xcode Test for iOS". We won't change any of the default parameters of this step. This step will run the tests and also output a variable, $BITRISE_XCRESULT_PATH, which contains the path to the xcresult file.

SonarQube expects the coverage data in a specific XML format. So after Xcode runs the tests and generates the xcresult, we need to get from there the coverage data and transform it into the format expected by SonarQube. We will be using the script from the SonarQube Code Coverage examples to do that. So we need to tell Bitrise to fetch the script and run it.

In our pull request workflow in Bitrise, we're adding the "File Download" step. We tell it to download the script from the URL https://raw.githubusercontent.com/SonarSource/sonar-scanning-examples/master/swift-coverage/swift-coverage-example/xccov-to-sonarqube-generic.sh to the destination path xccov-to-sonarqube-generic.sh and we set the file permissions to 755 (to make sure it's executable).

The script has jq as a dependency, which is a tool for processing JSON. We can install this via Homebrew, so we add another step for this. We specify jq as the formula name and leave the rest of the parameters unchanged.

Now we have everything we need to run the script we downloaded and extract the coverage data from the xcresult into the format that SonarQube expects. So we add the Run Script step And we add the following script content:

#!/usr/bin/env bash
# fail if any commands fails
set -e
# make pipelines' return status equal the last command to exit with a non-zero status, or zero if all commands exit successfully
set -o pipefail
# debug log
set -x

echo "Converting code coverage log to Sonar format"
./xccov-to-sonarqube-generic.sh $BITRISE_XCRESULT_PATH > cov.xml

We're running the script on the xcresult file and exporting the coverage data to a file called cov.xml.

Uploading the results to SonarQube

With the coverage data in the cov.xml file, now we can run sonar-scanner. We already had this setup on Bitrise, using the SonarQube Scanner step made by DroidsOnRoids, but we didn't have the coverage data. We do now, so we just have to add this line sonar.coverageReportPaths=cov.xml in the step's options under "Scanner parameters in Java properties format".

Overall, this is what our pull request workflow looks like in Bitrise:

There can be variations based on your specific project (dependency manager, etc), so use this as inspiration and not as an absolute source of truth.

We can now open a new pull request to test this workflow in Bitrise. We're not covering setting up the workflow trigger in this article, you can check out Bitrise's official guide for that.

After the Bitrise workflow has successfully been run, we can now see the results in the SonarQube dashboard, showing some data for code coverage.

Wrap-up

Getting the code coverage data into SonarQube is not a complicated task, but it requires a bit more work than we initially expected. We found this way of doing it, which relies on the script from the SonarSource swift examples. This is a solution that works for now, but it is possible that in the future the script will break and not work with new versions of Xcode. We will be keeping an eye on this and updating our workflow if necessary.

Article Photo by Mikail McVerry

code coveragesonarqubebitrise

Author

Marius Constantinescu

Marius Constantinescu

iOS Director

iOS director at Monstarlab EMEA. šŸ· WSET Level 3 distinction.

You may also like

August 18, 2022

Accessing AWS RDS databases remotely with no exposed ports

Ok, I admit it. The title might sounds weird because, how it is supposed to connect to an SQL service without a port, right? Well the catch is that there IS a port, but it is not an inbound port, therefore nothing is exposed. And it is fully managed by AW...

Juan Eduardo CastaƱo Nestares

Juan Eduardo CastaƱo Nestares

Solution ArchitectureNETSitecore

July 15, 2022

A Guideline to GitHub Actions with CI Pipeline

CI Pipelines help improve efficiency by automating complex workflows. With GitHub Actions, it's easier than ever to bring CI/CD directly into your workflow from your repository. Put together with the CI pipeline, a series of automated workflows that help ...

Sabrina Rashid

Sabrina Rashid

QA