So, after a days research I came across 3 plugins : EMMA, Cobertura and Clover.
I will not go into details of clover as it is paid and has licensing issues (you need license war's although you can get 30 day trial war). I somehow found it difficult to integrate with tomcat.
I was pretty new to understand how code coverage is computed. After doing some research I figured out that it involves 4 steps :
1) Instrumentation : All classes will be added with some extra code which help analyze line hits in code coverage later. So, plugin will generate instrumented jar and an additional file like (.em/.ec by emma or .ser file by cobertura).
2) Running test cases/Deployment on J2EE container : Running in test phase is straight forward.
To deploy in say tomcat in my case, firstly, you need to specify environment variable to where plugin will dump instrumented data for during test phase on tomcat.
3) After tomcat is deployed, junits are run. And when tomcat stops, plugin will dump the instrumented data file which will be used to generate code coverage report.
4) Merge dump files and generate report in different formates like html,xml,txt.
Now, each plugin has a different way of dumping runtime data and initial instrumentation data. Lets discuss EMMA and Cobertura in their approach (Note : Please choose maven "phase" according to your needs)
Cobertura
Before we look into cobertura, a word of caution. If your project uses spring and jdk proxies, please use EMMA instead, as in my case. Cobertura has problems with org.springframework.aop.framework.ProxyFactoryBean and jdk proxies. If you are using AOP proxies and have annotation at class level and not interface level, then you can use cobertura.
1) To instrument classes use cobertura-maven-plugin .
Here is a snippet to instrument jars
cobertura net.sourceforge.cobertura cobertura true 1.9.4.1 org.codehaus.mojo cobertura-maven-plugin cobertura-instrument process-classes instrument
This will generate a .ser file which will contain meta data about each class. It is important that before deploying, .ser should contain meta data about all the classes you are interested in finding. Say if you have 2 different jar's instrument in 2 different projects, use cobertura-merge before deploying on tomcat (if you are interested in code coverage of jar 1 in project 2..say common library in my case). This can be done using ant task (do only if you need to merge 2 different metadata ser before hand. In single project it is not needed). You can choose appropriate phase before deployment. In my project, I used it at jar verify stage.
maven-antrun-plugin 1.6 merge-ser-pre verify < taskdef classpathref="maven.runtime.classpath" resource="tasks.properties" /> < taskdef classpathref="maven.runtime.classpath" resource="net/sf/antcontrib/antcontrib.properties" /> < echo message="Executing cobertura merge" /> < include name="cobertura.ser" /> < include name="cobertura.ser" /> run ant-contrib ant-contrib 20020829
Now, to deploy on tomcat you need following dependency in war packaging
I am using cargo plugin to start tomcat..so here is how to set dump file system vairable :net.sourceforge.cobertura cobertura 1.9.4.1 jar compile
... somelocation/cobertura.ser
It is extremely important to note that this dumping .ser should be same as previously metadata instrumented .ser . After runtime, EMMA should dump information into same .ser which was instrumented initially during jar creation or merged ser in case of multi projects or else code coverage will be 100%.
Finally, we need to create a report from this .ser . If you have different .ser from different projects computed separately, you can again use cobertura merge to merge them into a final ser.
Cobertura reports are better as html reports looks visually much better that EMMA. Apart from lines covered, cobertura report also tells how many times each line was hit. This is not covered in EMMA.
org.apache.maven.plugins maven-antrun-plugin verify < taskdef classpathref="maven.runtime.classpath" resource="tasks.properties" /> < taskdef classpathref="maven.runtime.classpath" resource="net/sf/antcontrib/antcontrib.properties" /> < available file="./1.ser" property="ser.file.exists" /> < equals arg1="${ser.file.exists}" arg2="true" /> < echo message="Executing cobertura report" /> < mkdir dir="${project.build.directory}/site/cobertura" /> < cobertura-report format="xml" srcdir="../java/src/main/java" destdir="${project.build.directory}/site/cobertura" datafile="./final.ser" /> < fileset dir="../commons/src/main/java" /> < fileset dir="../algo/java/src/main/java" /> < fileset dir="../practise/java/src/main/java" /> < echo message="No SER file found."/> run ant-contrib ant-contrib 20020829
EMMA
EMMA is relatively easier to integrate. For instrumentation initially use :
emma org.codehaus.mojo emma-maven-plugin 1.0-alpha-3 true process-classes instrument
This will create .em file . EMMA does not want you to put this .em file in tomcat container unlike cobertura which uses same .ser file to dump runtime information. So, just deploy your war on tomcat with your choosen new dump file path.
you will need following dependency :
emma emma 2.1.5320 jar compile
Here is code in cargo :
false ${basedir}/target/final.ec
If you have multiple projects to be build, emma sometimes will give you "java.net.BindException:Address in use" error and not allow tomcat to start. This can either be solved by using emma.rt.control.port system variable and setting different values for different project jars. But a better approach is to somehow disable it using emma.rt.control, setting it to false(Thats why comment port)
After tomcat shuts, it will generated this final.ec
And finally we need to merge (in case of multi projects ) and create final report. Here is the code :
emma emma 2.1.5320 jar compile emma emma_ant 2.1.5320 jar compile maven-antrun-plugin 1.6 report emma verify < taskdef classpathref="maven.runtime.classpath" resource="emma_ant.properties" /> < sleep seconds="15" /> < include name="algo/webapp/target/final.ec" /> < include name="algo/java/target/coverage.em" /> < include name="practise/webapp/target/final.ec" /> < include name="practise/java/target/coverage.em" /> < include name="target/final.emma" /> < txt outfile="target/coverage.txt" /> < html outfile="target/coverage.html" />run ant-contrib ant-contrib 20020829
Congrats..check your report :)
I spent almost 4 night-outs on integration maven with cargo and integration tests. Hope you are able to do it quickly :)
No comments:
Post a Comment