Exercise 6: SonarQube

This optional exercise provides a basic introduction to source code analysis using SonarQube. If you choose to do it, you should use your own PC, not a School of Computing lab machine.

Preparation

  1. Download the code for this exercise into the top level of your repository and unzip the file. This should create a directory named exercise6.

  2. Visit the Try Out SonarQube page. Find the section on installing a local instance of SonarQube from a Zip file, and follow the instructions.

    After issuing the command to run SonarQube, wait for the message ‘SonarQube is up’ to appear in the terminal window before you attempt to login via a web browser. This might take a few minutes…

Setting Up a Project

  1. After logging in to SonarQube in your browser, click the Create New Project button. Specify ’exercise7’ as the project key and display name, then click Set Up.

  2. Specify ’exercise6’ as the token name and click the Generate button. This will generate a unique token that will be used to link the results of code analysis with the project you have created in SonarQube.

  3. Click the Continue button, then specify Java as the main language of the project and Gradle as the project build system.

    At this point, SonarQube will display a Gradle command that can be used to perform code analysis and update SonarQube with the results. Leave the page open in your browser so you can copy this command in the next phase of the task.

Analyzing The Code

  1. Open a terminal window if necessary and cd to the exercise6 directory.

  2. Copy the Gradle command displayed by SonarQube (use the handy Copy button in the top-right corner of the panel). Paste the command into your terminal window and run it.

    Gradle will run the unit tests, measure the code coverage provided by the tests, then perform further analysis of code quality. It will then upload the results to the SonarQube server.

  3. When the Gradle task has completed, return to the browser. On the Overview tab you will now see a dashboard summarizing the results of code analysis.

    Screenshot of SonarQube's project dashboard

    SonarQube dashboard

    Note the following features:

    • The quality gate status is ‘Passed’, coloured green. This indicates that the code passes the default thresholds on code quality set by SonarQube.

    • The code gets an ‘A’ rating for reliability, security and maintainability, but SonarQube has detected 5 code smells, which have incurred an estimated 52 minutes of technical debt – in other words, SonarQube reckons that it will take a developer nearly 1 hour to eliminate the code smells.

    • Code coverage by the unit tests is very good, but not 100%.

    • There are two blocks of code that SonarQube sees as duplicates of each other. Together, these blocks represent nearly 16% of the lines of code in the project.

  4. Click on the Measures tab. As an overview of the project, SonarQube plots code coverage versus estimated technical debt for all the classes. Each class is plotted as a circle whose radius is proportional to the number of lines of code. You can click on a circle for more details about a class. The ideal position for classes is the bottom-left corner of the graph.

    SonarQube project overview: code coverage versus technical debt

    Code coverage vs technical debt

  5. In the list of categories on the left of the screen, expand the ‘Maintainability’ category and click on the Overview link to see a plot of technical debt versus lines of code. As before, each class is circle. Circle colour indicates class maintainability, on a scale from green (‘A’-rated) to red (‘E’-rated). Circle radius is proportional to the number of code smells detected in the class. Small green circles at the bottom of the plot are best here.

    SonarQube plot of technical debt versus lines of code

    Technical debt vs lines of code

  6. In the list of categories on the left of the screen, expand the ‘Coverage’ category and click on the Overview link to see a plot of code coverage versus cyclomatic complexity. Small circles at the bottom of the plot, concentrated more towards the bottom-left corner, are best here.

    SonarQube plot of code coverage versus cyclomatic complexity

    Code coverage vs cyclomatic complexity

  7. Finally, expand the ‘Complexity’ category. This will show both the total cyclomatic complexity for the project and the total cognitive complexity. The distinction is important here. Increases in cyclomatic complexity need not be a serious concern unless they are accompanied by increases in cognitive complexity.

Exploring The Issues

  1. Click on the Issues tab to view the code smells in more detail:

    Code smells listed on SonarQube's Issues tab

    Code smells identified by SonarQube

    The five smells are distributed across the Customer and Price classes.

  2. Expand the ‘Severity’ category on the left of the screen to see the severity filters. Use these filters to see which of the smells are regarded as minor issues and which are regarded as major issues.

  3. If you are unsure about why SonarQube has identified these code smells, click on the ‘Why is this an issue?’ link.

  4. Click on an issue to see its location in the code.

Improving The Code

  1. Start by investigating code coverage further. Although you can do this via SonarQube, you’ll be able to see coverage more clearly by viewing the report generated by the JaCoCo Gradle plugin.

    Open build/reports/jacoco/test/html/index.html in a web browser and navigate through the code via the links. You will find that one line of the Car class is highlighted in red, indicating that it has not been touched by the unit tests.

  2. Fix the issue by adding an appropriate unit test to the CarTest class. Run the tests with

    ./gradlew test
    

    They should all pass.

    Reopen the JaCoCo report in your browser. Coverage should now be 100%.

  3. Now return to SonarQube and examine the minor issue regarding failure to use the isEmpty() method. Fix this issue and make sure that the unit tests still pass.

  4. Use Gradle to rerun the code analysis for SonarQube.

  5. Examine the minor issue regarding use of an abstract class for Price. Implement the change suggested by SonarQube (i.e., convert it to an interface, with getFrequentRenterPoints() as a default method.) Make sure that the unit tests still pass.

  6. Use Gradle to rerun the code analysis for SonarQube.

  7. Examine the results of the analysis. You should find that the Overview tab in SonarQube now shows 100% code coverage and only one remaining code smell. There will also be an Activity graph at the bottom of the page, showing how the number of issues has fallen over time.

  8. Switch to the Measures tab and examine some of the visualizations seen earlier, to see how they have changed.