Over a million developers have joined DZone.
Platinum Partner

Code Metrics in Minutes

· Agile Zone

The Agile Zone is brought to you in partnership with JetBrains. Learn how Agile Boards in YouTrack are designed to help teams plan, visualize and manage their work in an efficient manner, with support for both Scrum and Kanban processes.

One of the primary goals of every developer should be to prevent or drastically limit the number of bugs or defects from being introduced in their source code. It is also our responsibility to write good, extensible, testable, and maintainable code. This however seems like a herculean task to many. John Smart has very well said in his latest and greatest "Java Power Tools" book:

When used well, software metrics can provide valuable feedback on the quality of the code being written, and allow the development team to learn and progress. To be successful, software metrics should be considered a team sport.

So, lets automate the task of finding defects early by using open source tools which can look at your source code and in most cases find, if not all, at least some potential defects. There are numerous open source tools like:

1. CheckStyle - is a development tool to help programmers write Java code that adheres to a coding standard.

2. JDepend - traverses Java class file directories and generates design quality metrics for each Java package.

3. JavaNCSS - cyclomatic complexity tool.

4. Simian - identifies duplication in Java.

5. Emma - Code coverage tool.

There are several other open source tools as well, like PMD, Cobertura, FindBugs and many more. All these tools are highly configurable as well. I mentioned the above five for a reason. I will get to it soon.

Imagine how much work it is to setup, configure, and run these metric tools as part of your continuous integration. It really is a huge task doing it for each and every project you have.

However, there is just one tool which you need to download: Panopticode. Panopticode includes all the above mentioned tools preconfigured. If you have read Neal Ford's "The Productive Programmer", chapter 7: Static Analysis" page 113, the author talks about "Generating Metrics with Panopticode". That's how I got to know about this amazing tool. There is no detailed instructions in the book on how to get this up and running, the web site does have.

So, I decided to give it a try and here are the steps I followed. Rather than creating a new project, I re-used the PetStore project which I have been using for a long time for all the articles I write.

Follow these steps to get Panopticode up and running:

1. Download Panopticode from here.

2. Unzip and copy to your project folder.

The folder structure will look like this:

3. Make changes to the build.xml file.

In the Panopticode web site, there are 4 steps listed which you can follow. However, rather than copying the entire build file, I modified my existing build file, and ran the new target metrics within the Hudson(Continuous Integration Server) Job .

Add the following lines from the panopticode/build-example.xml to your build file.


<import file="panopticode/panopticode-imports.xml" />


<target name="metrics" depends="clean"><panopticode projectdir="${basedir}" projectname="${ant.project.name}" projectversion="${version}" srcdir="${srcdir}"></panopticode></target>

In the above target, specify the path to your source directory.

3.c Modify your target which compiles and runs your unit tests to include the following lines:

<panopticode-junit unittestclasspathid="unittest.path" outputdir="target"></panopticode-junit></code><panopticode-junit unitTestClasspathId="unittest.path"                           outputDir="target">            <batchtest todir="target/rawmetrics/xml/junit">                <fileset dir="target/classes" includes="**/*Test.class" />            </batchtest>        </panopticode-junit><code><panopticode-junit unittestclasspathid="unittest.path" outputdir="target">            <batchtest todir="target/rawmetrics/xml/junit">                <fileset dir="target/classes" includes="**/*Test.class">            </fileset>        </batchtest></panopticode-junit>

Make changes to the unitTestClasspathId to include the libraries required to run your tests. In my case, I included the JEE libraries required for my EJB application.

4. Run the metrics Ant target

Run the metrics target either from the command line. You should see an output like this:

[junit] Testcase: validNumberOfLifecycleAnnotations took 0.008 sec
[report] processing input files ...
[report] 2 file(s) read and merged in 4 ms
[report] writing [xml] report to [../CodeMetricsProject/target/rawmetrics/xml/emma.xml] ...
[report] writing [html] report to [../CodeMetricsProject/target/rawmetrics/html/emma/emma-coverage.html] ...
[emmaPanopticode] Loading panopticode structure: panopticode.xml
[emmaPanopticode] Loading supplement: org.panopticode.supplement.emma.EmmaSupplement
[emmaPanopticode] Writing back to panopticode structure: panopticode.xml
[mkdir] Created dir: ../CodeMetricsProject/target/reports/svg
[echo] Building Static Reports
[echo] Building Interactive Reports
Total time: 8 seconds

5. Force a build.

Now that we have all the xml files generated for the metrics tool, we need to make sure run the above target metrics from the Hudson Job, and force a build. You should be able to see the following xml as well as HTML files generated:

6. Configure the XML files.

Finally, configure all these xml files within the Post-Build actions of the Hudson Job, and you should be able to force a build and see the reports in your dashboard. See screen shots below for various metrics:

a. Hudson Dashboard:

b. Emma Coverage Trend:

c. Check Style:

d. JavaNCSS:

7. Troubleshooting.

A few problems I found getting this up and running:

If you see the build failed with the following exception, copy the JDepend library to your ANT_HOME/lib folder.

    [mkdir] Created dir: ../CodeMetricsProject/target/classes
    [javac] Compiling 22 source files to ../CodeMetricsProject/target/classes
    [javac] Note: Some input files use unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
     [echo] Panopticode - Using JDepend for OO metrics
     [echo] If you get an error stating 'Could not create task or type of type: 
jdepend' then you need to copy the jdepend-2.9.1.jar file to your 
ANT_HOME/lib directory.BUILD FAILED../CodeMetricsProject/build.xml:54: The following error occurred 
while executing this line:../CodeMetricsProject/panopticode/panopticode-imports.xml:125: 
The following error occurred while executing this line:../CodeMetricsProject/panopticode/supplements/jdepend/jdepend-imports.xml:38: 
Problem: failed to create task or type jdependCause: the class org.apache.tools.ant.taskdefs.optional.jdepend.JDependTask 
was not found.        This looks like one of Ant's optional components.Action: Check that the appropriate optional JAR exists in        -/usr/share/ant/lib        -/Users/meerasubbarao/.ant/lib        -a directory added on the command line with the -lib argumentDo not panic, this is a common problem.The commonest cause is a missing JAR.This is not a bug; it is a configuration problemTotal time: 5 secondsPublishing JavadocRecording Emma reports CodeMetricsProject/reports/emma.xmlfinished: FAILURE

In the Panopticode-imports.xml file, you see the following comments:

However, if you try to comment the import for emma and you cobertura import definition, you get an error as shown below:

Buildfile: ../CodeMetricsProject/build.xml

../CodeMetricsProject/build.xml:3: The following error occurred 
while executing this line:../CodeMetricsProject/panopticode/panopticode-imports.xml:42: 
Cannot find plugins/cobertura/cobertura-imports.xml imported from 
../CodeMetricsProject/panopticode/panopticode-imports.xmlTotal time: 223 milliseconds

Now, if I go back and change it to the directory where I found the cobertura-imports.xml file (supplements), I get an exception like this:

[cobertura-report] Report time: 263ms
     [move] Moving 1 file to ../CodeMetricsProject/target/rawmetrics/xml
   [delete] Deleting directory ../CodeMetricsProject/target/rawmetrics/xml/cobertura
   [delete] Deleting: ../CodeMetricsProject/cobertura.ser

../CodeMetricsProject/build.xml:54: The following error occurred 
while executing this line:../CodeMetricsProject/panopticode/panopticode-imports.xml:145: 
emmaFile emma.xml does not existTotal time: 7 seconds

Next, I changed the report file to cobertura.xml, and the build complained about:

[cobertura-report] Report time: 264ms
[move] Moving 1 file to ../CodeMetricsProject/target/rawmetrics/xml
[delete] Deleting directory ../CodeMetricsProject/target/rawmetrics/xml/cobertura
[delete] Deleting: ../CodeMetricsProject/cobertura.ser
[emmaPanopticode] Loading panopticode structure: panopticode.xml
[emmaPanopticode] Loading supplement: org.panopticode.supplement.emma.EmmaSupplement

../CodeMetricsProject/panopticode/panopticode-imports.xml:145: null

Total time: 8 seconds



Finally, I downloaded the source code to see the classname for this taskdef, couldn't find one and just gave up at this point. You should be able to generate coverage report for Emma with no problems at all.

As you can see from this article, it is just a few minutes to setup and start using Panopticode. As I mentioned earlier also, there are many open source tools available, that can improve the quality of your code and also keep track of the same if they are automated and are part of your continuous integration. I am sure once you have these open source tools integrated, you will keep wondering how you developed code without them.

The Agile Zone is brought to you in partnership with JetBrains. Learn how Agile Boards in YouTrack are designed to help teams plan, visualize and manage their work in an efficient manner, with support for both Scrum and Kanban processes.

java,agile,hudson,code coverage,opinions,code metrics,javancss,checkstyle,emma

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

{{ parent.tldr }}

{{ parent.urlSource.name }}