Quality Assurance With Sonar

DZone 's Guide to

Quality Assurance With Sonar

· Java Zone ·
Free Resource

It's incredible how unknown a tool like Sonar is yet. I guess Gradle suffers the same destiny. After all, they're both similar in their intent, improve the quality of your software. It seems lots of people know about unit testing (not so many about code coverage), less know about tools like Checkstyle or FindBugs (static analysis of code) and just a minority are aware of other esoteric metrics like cyclomatic complexity. And even the few that use all of them do not extract all the value that a dashboard provides. That's what Sonar handles, it will take your project and stress it showing the results in a visually appealing site. With no extra work from you, the only requirement is to use Ant or, preferably, Maven.

But seeing is believing so I'll try to convince you showing the whole process and what kind of enhancements you'll be getting. As the demo project I've chosen IWebMvc2. I've nearly finished the development by now so it's a perfect timing to improve quality. In addition it's a complex web application made of three different sub-projects so something must arise. IMHO the quality of the code is pretty good, in theory I just want proofs...did I just say humble? ;-).

The first task is downloading the project and installing it. It's trivial believe me (well as long as you know how to unpack an archive...). To run Sonar just go to the bin folder, select your OS and execute the provided script. Trivial again. Sonar show be accessible (although empty) at http://localhost:9000 by now. Go there and login with admin/admin. Select configuration and under Quality Profiles click on Sonar way with Findbugs: set as default.

Next step is to build our project and include the Sonar phase. This is done typing:

mvn clean compile sonar:sonar

Pretty easy, wasn't it? If the project was built successfully the console was updated and shows something like:

A quick glance reveals a row per project analyzed indicating the number of rules violated and the coverage of the unit tests. There's a little bug with the latest JDK and Cobertura that reports 0% coverage always. As a workaround use JDK6_Update13 for example. The build time reflects how long ago was this information retrieved (not how long took the build itself, tricky). One click on the project shows the dashboard (this is a trimmed version):

Here's the bread and butter! All kind of metrics! From the whole project. The graphic displays the number of modules (JARs) and the relative size of each one. It's used to drill down and get module specific statistics. In fact, every link allows to navigate to new pages with deeper details.

Our task is to improve the quality of the project (bit by bit) so we can navigate to the Violations section and get a detailed report of the problems:

The rules are divided in several areas, some are require while others are optional. Selecting one rule gives the complete list of locations where the code fails to comply. Selecting one of those locations highlights the code:

In the above example Sonar has detected a private method that is never called. For performance and maintainability it should be removed altogether. Now, this is not true at all because I KNOW this method is called using reflection. So I should just ignore this error (caution! static analysis tools are not perfect!). Otherwise I could simply open an IDE and correct the mistake.
Of course Sonar remembers previous scenarios and can track the project life cycle (time machine they call it). Ideally you should be tying Sonar with a Continuous Integration server (out-of-the-box includes a Hudson
I'm not gonna lie, quality requires effort. Even if you're an outstanding programmer. Sonar will just help (a lot actually) by providing visual and reporting tools but expect a slow (sometime tedious) climb to the top. Fortunately, in the end, it pays dividends.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}