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

November 7, 2024

Introducing Shorebird, code push service for Flutter apps

Update Flutter apps without store review What is Shorebird? Shorebird is a service that allows Flutter apps to be updated directly at runtime. Removing the need to build and submit a new app version to Apple Store Connect or Play Console for review for ev...

Christofer Henriksson

Christofer Henriksson

Flutter

May 27, 2024

Introducing UCL Max AltPlay, a turn-by-turn real-time Football simulation

At this year's MonstarHacks, our goal was to elevate the sports experience to the next level with cutting-edge AI and machine learning technologies. With that in mind, we designed a unique solution for football fans that will open up new dimensions for wa...

Rayhan NabiRokon UddinArman Morshed

Rayhan Nabi, Rokon Uddin, Arman Morshed

MonstarHacks

ServicesCasesAbout Us
CareersThought LeadershipContact
© 2022 Monstarlab
Information Security PolicyPrivacy PolicyTerms of Service