Healthier cleaner code in your Android projects
One of the key points in a CI process is to increase code quality of your codebase. One way of doing that is to insure that the code coverage always increases while technical debt decreases, making code more reliable and secure.
In this post we will talk about two tools that can help us keep track of our code, Codecov and Sonarqube, by analysing our code reports.
Overview
Before going in details lets take a quick overview on these tools.
Codecov
Provides highly integrated tools to group, merge, archive, and compare coverage reports. Some of its key features are:
- Compare coverage reports between branches
- Pull request analysis and decoration with detailed report
- No configuration needed, plug and play
- If needed can be configured through yml file
- Enterprise version
Sonarqube
An open-source tool for continuous code quality that measures and analyses source code and coverage reports. Some of its key features are:
- Open source
- Free to download and install or use it as an external service (Sonarcloud)
- Continuously code monitoring with various reports like security, potential bugs, code smells and duplicated code
- Pull request analysis and decoration with detailed reports
- Configurable through web interface
Generate reports
In order to start using these tools we need first to generate our code reports. For this task we will use a Jacoco gradle plugin for Android. This plugin will create all corresponding Jacoco tasks on every module that project contains, including a task that merges all reports into a single one, with no extra configuration.
In order to add Jacoco, add below code to root gradle script
buildscript {
dependencies {
. . .
classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:0.16.0"
}
}
apply plugin: "com.vanniktech.android.junit.jacoco"
junitJacoco {
jacocoVersion = '0.8.4'
includeNoLocationClasses = true
includeInstrumentationCoverageInMergedReport = true
}
To get coverage reports for instrumentation tests also, enable testCoverageEnabled flag
android {
buildTypes {
debug {
testCoverageEnabled true
}
}
}
To generate the reports we can run
./gradlew jacocoTestReportDebug
for unit test reports./gradlew combinedTestReportDebug
for both unit and ui test reports. Keep in mind that for this case an emulator must be up and running, in order to execute ui tests and generate the reports
and finally to merge them all in one single report ./gradlew jacocoTestReportMerged
.
Codecov Integration
One of the key features that Codecov offers is its fast, plug and play integration, without the need to configure or add additional plugins.
Once we login to our Codecov account and select our project, Codecov will generate a unique token. All we have to do is to set that token as environment variable in our CI provider CODECOV_TOKEN="token"
and just upload the reports using the bash uploader bash <(curl -s https://codecov.io/bash
. For testing purposes on our local machine, we can set token directly on bash uploader bash <(curl -s https://codecov.io/bash -t token
, but we should avoid exposing tokens on CI configuration files.
That’s it, Codecov will find our code reports, upload and analyse them and comment the detailed report in the according pull request.
You can find a sample integration here and a sample pull request comment here.
Sonarqube Integration
In order to start using Sonarqube and analyse our project we have to use an additional SonarScanner gradle plugin. This plugin gives us the ability to start the analysis by running a simple gradle task, without the need of complicated configuration.
In order to add SonarScanner, add below code to root gradle script
buildscript {
dependencies {
. . .
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.8"
}
}
apply plugin: "org.sonarqube"
After adding the plugin we need to configure some of its properties in order to be able to upload all necessary data in our Sonarqube instance
sonarqube {
properties {
property "sonar.projectVersion", "1.0"
property "sonar.projectName", "name"
property "sonar.projectKey", "key"
property "sonar.organization", "organization"
property "sonar.host.url", "http://localhost:9000/" // or use an external service like https://sonarcloud.io/
property "sonar.login", "unique_generated_token_from_sonar"
property "sonar.language", "kotlin"
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.coverage.jacoco.xmlReportPaths", "${rootProject.projectDir}/app/build/reports/jacoco/debug/jacoco.xml"
}
}
and then just run ./gradlew sonarqube
. Sonarqube will analyse provided reports along with the code and will generate the appropriate reports according to its findings.
Pull request decoration won’t work out of the box as Sonarqube needs a bit more configuration
sonarqube {
properties {
. . .
property "sonar.pullrequest.key", "5" // Unique identifier of PR
property "sonar.pullrequest.branch", "feature" // Name of PR branch
property "sonar.pullrequest.base", "master" // Target branch name
property "sonar.pullrequest.provider", "github"
}
}
Running ./gradlew sonarqube
after setting these extra properties will result with Sonarqube commenting on selected PR with the detailed report.
You can find a sample configuration with Travis CI integrated here, along with a sample integration and a sample pull request comment.
Summary
Codecov offers an out of the box, plug and play solution to track code coverage, while Sonarqube offers a more powerful solution that help us improve our code and keep it clean.