Staying ahead of your bugs - quality metrics for developing Atlassian plugins with SonarQube

13 min read /
If you're passionate about developing top-quality software, that passion could well take up most of your time. As a father of two, a basketball enthusiast and a hobby guitarist, I often found myself working on code when I would have liked to spend time on my other interests. Luckily, I discovered SonarQube, a tool that makes it easier for me to trust the code I’m developing or maintaining. SonarQube gives me insights that were previously hard to obtain. And that helps me to enjoy more leisure time. Maybe it can do the same for you.

SonarQube's quality dashboards are a useful tool for monitoring the quality of your code against a defined rule set and based on standard metrics. This blog post is complemented by two videos, and it provides you with the ready-made Maven configuration required to integrate SonarQube into your Continuous Integration (CI) build process.

Benefits of SonarQube

SonarQube is an 'open platform for managing code quality' that lets you assess your code from a variety of perspectives, including

  • Coding rules
  • Metrics such as complexity, and
  • Dynamic measurements like code coverage in integration and unit tests.

Furthermore, it can be employed and extended free of charge. At the same time, professional support is available, as are commercial plugins that extend its scope. And since it meshes nicely with Maven, using the tool alongside your Atlassian plugin development environment is straightforward.

And in case you were wondering: SonarQube is indeed the tool formerly known as Sonar.

Continuously assess your code quality

Quality management with SonarQube is based on the analysis and measurement of your source code. Three types of measurement are used to assess code quality:

  • Basic metrics (such as lines of code and number of classes), which give you an impression of the size and complexity of your code.
  • Static analysis, i.e. the evaluation of rules against your code – e.g. are you complying wiht the naming conventions, or are you using any well-known anti-patterns, such as multi-threaded use of the SimpleDateFormatter.
  • And last but not least, the dynamic measurement of code coverage for your unit and integration tests.  

The findings of these measurements are conveniently included in various management views and/or dashboards. Moreover, you can always drill down to the underlying code, or compare current measurements with earlier ones. This proves extremely useful for identifying trends in your code base.  

Using SonarQube to develop kick-ass Confluence add-ons

At K15t Software, we use SonarQube to safeguard the high quality of our code. The first video begins by offering an overview of our in-house software development environment – which, unsurprisingly, includes a host of Atlassian tools. The video then describes the capabilities of SonarQube which extend and enhance that environment. This section represents an executive summary.

SonarQube tutorial – setting up plugin development projects

The second video is a hands-on tutorial that explains how to set up a plugin development project for SonarQube, and gives you an impression of the SonarQube UI’s look & feel.

We'll add a profile and probably, you should only execute this profile on your CI server (of course you use Atlassian Bamboo (smile)). Executing the SonarQube tasks will take some time. Most of the profile is devoted to telling Maven how to record coverage using the JaCoCo plugin.

Here are the additions required in your pom.xml document to integrate SonarQube into your CI build. Add the following profile and modify at the TODO tag, if you're developing code for a product other than JIRA:

<profile>
    <id>sonar</id>
    <activation>
        <activeByDefault>false</activeByDefault>
    </activation>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.6.3.201306030806</version>
                <executions>
					<execution>
                        <id>pre-unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                            <propertyName>jacocoSurefire</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                            <dumpOnExit>true</dumpOnExit>
                            <propertyName>jacocoIntegration</propertyName>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <append>true</append>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>${jacocoSurefire}</argLine>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <!-- TODO: Here you'll have to put confluence / bamboo etc. to integration test for other Atlassian products -->
				<artifactId>maven-jira-plugin</artifactId>
                <configuration>
                    <jvmArgs>${jacocoIntegration}</jvmArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <!-- Reuse reports prevents SONAR from running the  -->
        <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
        <!-- Where will sonar find the Test reports - see tasks "Flatten directory for Sonar" on bamboo in video. -->
        <sonar.junit.reportsPath>target/test-reports</sonar.junit.reportsPath>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
		<!-- By splitting integration and unit test you will be able to identify lines covered in either one or both -->
        <sonar.jacoco.itReportPath>target/coverage-reports/jacoco-it.exec</sonar.jacoco.itReportPath>
        <sonar.jacoco.reportPath>target/coverage-reports/jacoco-ut.exec</sonar.jacoco.reportPath>
 
		<!-- These properties could be in your settings.xml -->
		<sonar.jdbc.url>jdbc:postgresql://192.168.1.70/sonarqube</sonar.jdbc.url>
		<sonar.jdbc.username>sonarqube</sonar.jdbc.username>
        <sonar.jdbc.password>secret</sonar.jdbc.password>
        <!-- Optional URL to server. Default value is http://localhost:9000 -->
        <!--sonar.host.url>http://myserver:9000</sonar.host.url-->
    </properties>
</profile>

When you're done, you can run 

mvn install -P sonar

which will execute your build as usual, and also collect coverage data for your unit and integration tests.

Next, you need to put all test reports (not including coverage reports) into a single folder, as SonarQube can't handle multiple directories. To do this, you could use the Maven resource or dependency copy plugin. I myself used a simple Bash script, because I only run SonarQube analyses on our CI server.

When you’ve done that, running 

mvn sonar:sonar -DskipTests

will analyze the source code and execute the rule sets using the results from the first mvn call. When the run is completed, you can view the results in the SonarQube UI.

Setting up your SonarQube platform

"Cool. But where is the SonarQube UI?” you ask. Hmmm, I should’ve explained that by now. You will, of course, need to set up and install SonarQube and its database before you get started. You'll find a useful description of how to do this in the SonarQube documentation, which was created using Atlassian Confluence. And incidentally, integrating SonarQube’s user management functionality with your Atlassian Crowd directory is simple: See the Crowd Plugin documentation.

What do you think? How do you measure the quality of your code? Just leave a comment below to discuss it with the community.

If you have any questions or other ideas about this approach, don't hesitate to email us at info@k15t.com.