This is the second installment in a series of posts about code quality, the tools that are available to track quality, and how to configure various systems to get all of the reporting.  There are a lot of posts on the internet about all of the tools and configurations that I'm going to describe, however, I thought it would be useful to have it all in one place.


Code Quality Unravelled: Part 1


What are multi-module projects?

There are times when you have a project that is made up of many components that you want to build together. When you have this setup there is a parent pom.xml and then each module is in a sub directory with its own pom.xml.

Aggregating Results

Multi-module projects have the ability to aggregate the quality reports and project information into one site. The site will include links to drilldown into each module as well as rolled up reports.

JXR, Javadoc, Checkstyle, JavaNCSS

Some plugins know how to handle aggregation without any extra configuration. JXR, Javadoc, Checkstyle, and JavaNCSS support aggregation with the same configuration that I listed in Part 1.


<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jxr-plugin</artifactId>
  <version>2.5</version>
</plugin>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-javadoc-plugin</artifactId>
  <version>2.10.3</version>
  <configuration>
    <additionalparam>-Xdoclint:none</additionalparam>
  </configuration>
</plugin>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>2.16</version>
</plugin>

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>javancss-maven-plugin</artifactId>
  <version>2.1</version>
</plugin>

Cobertura

Adding aggregation to Cobertura is as simple as adding an aggregate tag to the configuration section.


<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>cobertura-maven-plugin</artifactId>
  <version>2.7</version>
  <reportSets>
    <reportSet>
      <id>cobertura</id>
      <reports>
        <report>cobertura</report>
      </reports>
      <configuration>
        <aggregate>true</aggregate>
        <formats>
          <format>html</format>
          <format>xml</format>
        </formats>
      </configuration>
    </reportSet>
  </reportSets>
</plugin>

PMD/CPD, Surefire, and Taglist

In order to add aggregation for PMD, CPD, Surefire, and Taglist you need to add separate reportSets one for the individual module and one for the aggregate.


<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <version>3.5</version>
  <reportSets>
    <reportSet>
      <id>pmd-report</id>
      <reports>
        <report>pmd</report>
      </reports>
      <configuration>
        <skipEmptyReport>false</skipEmptyReport>
      </configuration>
    </reportSet>

    <reportSet>
      <id>pmd-aggregate</id>
      <inherited>false</inherited>
      <reports>
        <report>pmd</report>
      </reports>
      <configuration>
        <aggregate>true</aggregate>
        <skipEmptyReport>false</skipEmptyReport>
      </configuration>
    </reportSet>

    <reportSet>
      <id>cpd-report</id>
      <reports>
        <report>cpd</report>
      </reports>
      <configuration>
        <skipEmptyReport>false</skipEmptyReport>
      </configuration>
    </reportSet>

    <reportSet>
      <id>cpd-aggregate</id>
      <inherited>false</inherited>
      <reports>
        <report>cpd</report>
      </reports>
      <configuration>
        <aggregate>true</aggregate>
        <skipEmptyReport>false</skipEmptyReport>
      </configuration>
    </reportSet>
  </reportSets>
</plugin>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-report-plugin</artifactId>
  <version>2.18.1</version>
  <reportSets>
    <reportSet>
      <id>unit-tests</id>
      <reports>
        <report>report-only</report>
      </reports>
      <configuration>
        <linkXRef>true</linkXRef>
        <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
      </configuration>
    </reportSet>

    <reportSet>
      <id>unit-tests-aggregate</id>
      <inherited>false</inherited>
      <reports>
        <report>report-only</report>
      </reports>
      <configuration>
        <aggregate>true</aggregate>
        <linkXRef>true</linkXRef>
        <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
      </configuration>
    </reportSet>
  </reportSets>
</plugin>

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>taglist-maven-plugin</artifactId>
  <version>2.4</version>
  <reportSets>
    <reportSet>
      <id>taglist-report</id>
      <reports>
        <report>taglist</report>
      </reports>
      <configuration>
        <tagListOptions>
          <tagClasses>
            <tagClass>
              <displayName>Todo Work</displayName>
              <tags>
                <tag>
                  <matchString>todo</matchString>
                  <matchType>ignoreCase</matchType>
                </tag>
                <tag>
                  <matchString>FIXME</matchString>
                  <matchType>exact</matchType>
                </tag>
              </tags>
            </tagClass>
            <tagClass>
              <displayName>Architecture Review Needed</displayName>
              <tags>
                <tag>
                  <matchString>ARCH-REV</matchString>
                  <matchType>exact</matchType>
                </tag>
              </tags>
            </tagClass>
          </tagClasses>
        </tagListOptions>
      </configuration>
    </reportSet>

    <reportSet>
      <id>taglist-aggregate</id>
      <inherited>false</inherited>
      <reports>
        <report>taglist</report>
      </reports>
      <configuration>
        <aggregate>true</aggregate>
        <tagListOptions>
          <tagClasses>
            <tagClass>
              <displayName>Todo Work</displayName>
              <tags>
                <tag>
                  <matchString>todo</matchString>
                  <matchType>ignoreCase</matchType>
                </tag>
                <tag>
                  <matchString>FIXME</matchString>
                  <matchType>exact</matchType>
                </tag>
              </tags>
            </tagClass>
            <tagClass>
              <displayName>Architecture Review Needed</displayName>
              <tags>
                <tag>
                  <matchString>ARCH-REV</matchString>
                  <matchType>exact</matchType>
                </tag>
              </tags>
            </tagClass>
          </tagClasses>
        </tagListOptions>
      </configuration>
    </reportSet>
  </reportSets>
</plugin>

Not Everyone Plays Nicely

Unfortunately, not all of the reports we have talked about support aggregation. FindBugs and JDepend do not support aggregation, so when you run site you will have to look at these reports within each module instead of at the top level page. You can find more information about why FindBugs doesn't support this on the FindBugs site.

Generating the site

In addition to running the site report as I described in Part 1, there are a few other goals for the site plugin.

  • mvn site:site
    • Runs the site report putting the output in target/site
  • mvn site:stage
    • Runs the site report putting the output in target/staging
  • mvn site:deploy
    • Runs the site report and deploys the output to a location specified in a <distributionMangement> block

The generated reports contain deficiencies that you should be aware of:

  • Running maven site (or site:site) on a multi-module project will create links to the sub-modules that do not work. To get the links to work you will have to run site:stage or site:deploy after site:site.
  • For some reason when running site:stage, the cobertura report is a blank page. You can find the aggregate report for this in the target/site location.
  • The Surefire Report shows zeros for everything in the rolled up report, but the module reports still contain the information.

For a sample project that includes all of these reporting sections check out the repo on Github.


Code Quality Unravelled: Part 1


Comment