Sonarqube code coverage for Kotlin on Android with Bitrise
I’ve recently been working on an Android app that is 100% Kotlin with a full development CI pipeline. Having a good app means that the code is testable, which lead me to use Sonarqube for static code analysis and code coverage.
Since there is no official Kotlin plugin for Sonarqube yet, I looked at a third party plugin on github named, Sonar-Kotlin. This plugin is awesome, as it has another library called detekt integrated in it. Detekt is what does the static code analysis. What about the code coverage you ask? Well the Sonar-Kotlin plugin has the ability to give us code coverage reports, but there is some set up that needs to be done.
i.e: This post assumes you have Sonarqube setup and some kind of CI.
Getting the Sonar-Kotlin plugin installed is very simple. I have a Vm running on Google Compute Engine that has Sonarqube installed in a Docker container. Then pretty much followed the steps on the plugins Github page and it was installed.
- git clone https://github.com/arturbosch/sonar-kotlin
- cd sonar-kotlin
- ./gradlew build
- cp build/libs/sonar-kotlin-[enter_version].jar $SONAR_HOME/extensions/plugins
- cd $SONAR_HOME/bin/[your_os]
- ./sonar.sh restart
The CI i’m using for the project is Bitrise. This is a pretty awesome CI for its workflow editor and all its third party integration. One of those third party tools Bitrise provides is Sonarqube scanner.
Within Bitrise we will add our scanner properties so when the Sonarqube scanner build step is invoked, those properties will be executed accordingly.
sonar.sources=. sonar.login=$SonarToken sonar.projectKey=$BITRISE_APP_TITLE sonar.host.url=$SonarUrl sonar.report.export.path=sonar-report.json detekt.sonar.kotlin.config.path=default-detekt-config.yml sonar.java.binaries=target/classes sonar.sources=app/src/main/java sonar.tests=app/src/test/java sonar.java.coveragePlugin=jacoco sonar.jacoco.reportPaths=app/build/jacoco/testDebugUnitTest.exec
So for us to get a sonar code coverage report for Java code, we need to have a gradle task that will generate a Jacoco report. This is the same for Kotlin.
I found this article to help you get started with Jacoco.
Once we have that set up within our workflow, we need to run the following gradle command before the Sonarqube scanner task runs.
./gradlew clean jacocoTestReport
The scanner needs a Jacoco report to show code coverage in Sonarqube and the command above provides that for us.
If we run a build now, we will see the following Sonarqube report.
As seen above, we do not have code coverage, even though I said in the beginning the plugin supports code coverage for kotlin code.
This is due to the Kotlin class files not being generated in the same location as Java class files. For us to get around this, we need to add the location of the Kotlin class files to the sonar.java.binaries property.
This location can differ depending on your project. We need to keep the “target/classes” in order for the Java class files to be picked up as well.
We then run our CI build again and we get code coverage for our Kotlin code.
A lot of experimenting was done to get to this point. There is not much help out there in getting this working, which is the reason for me sharing my experience. I hope this helps everyone out there that is trying to solve the same problem I had.
Happy Sonarqube code coverage.
Get in Touch!
This article was originally published on Medium.com. https://android.jlelse.eu/sonarqube-code-coverage-for-kotlin-on-android-with-bitrise-71b2fee0b797