I am trying to get Cobertura working with my Ant build, and specifically just want it to give me a coverage report on my unit tests. I'm using the following directory structure:
src/main/java --> main source root
src/test/java --> test source root
bin/main --> where main source compiles to
bin/test --> where test source compiles to
gen/cobertura --> cobertura root
gen/cobertura/instrumented --> where "instrumented" class will be copied to
My understanding of Cobertura (and please correct me if I'm wrong!!) is that it adds bytecode to compiled classes (aka "instrumentation") and then runs reports based on that injected/woven bytecode.
So my question is, if Cobertura changes the bytecode of the classes its instrumenting, should I run JUnit on my test sources before <cobertura:instrument>, or after, and why?
You're correct that Cobertura instruments the byte code of your compiled classes. You normally want to exclude your test sources from coverage analysis, since the test classes are effectively the drivers that generate the coverage. The basic example build.xml provided with Cobertura gives a good example when it calls cobertura-instrument:
<cobertura-instrument todir="${instrumented.dir}">
<!--
The following line causes instrument to ignore any
source line containing a reference to log4j, for the
purposes of coverage reporting.
-->
<ignore regex="org.apache.log4j.*" />
<fileset dir="${classes.dir}">
<!--
Instrument all the application classes, but
don't instrument the test classes.
-->
<include name="**/*.class" />
<exclude name="**/*Test.class" />
</fileset>
</cobertura-instrument>
</target>
The exclude element here excludes all the classes with "Test" in their names from being instrumented.
Here's a working example of how the Cobertura ANT tasks are used in conjunction with Junit to generate a code coverage report
SONAR - Measure Code Coverage using Cobertura
Related
Executing apache cassandra tests using ant test command. Need to skip execution of few tests like org.apache.cassandra.audit.AuditLoggerTest , org.apache.cassandra.fql.FullQueryLoggerTest etc.
Tried excluding testfiles in https://github.com/apache/cassandra/blob/trunk/build.xml under <target name="_build-test"> however it didn't worked.
<exclude name="org/apache/cassandra/audit/AuditLoggerTest.java"/>
<exclude name="${test.unit.src}/org/apache/cassandra/audit/AuditLoggerTest.java"/>
#Ignore annotation for test classes works however I am looking for solution with build.xml
I have the following JUnit test in eclipse:
package test;
import org.junit.Test;
public class SimpleJUnitTest
{
#Test
public void doTest() { System.out.println("Test did run"); }
}
And the following build.xml in the same folder:
<?xml version="1.0" encoding="UTF-8"?>
<project name="LoggerTest" default="JUnitTest" basedir=".">
<target name="JUnitTest">
<junit>
<classpath location="../../lib/junit.jar" />
<test name="test.SimpleJUnitTest" />
</junit>
<echo>boo</echo>
</target>
</project>
If I run the test class under "Run As..." and choose JUnit, it runs without error. If I run the build.xml under "Run As..." and choose Ant Build, I get the following output:
Buildfile: C:\Users\995868\workspace\JUnit1\tst\test\build.xml
JUnitTest:
[junit] Test test.SimpleJUnitTest FAILED
[echo] boo BUILD SUCCESSFUL Total time: 390 milliseconds
If I remove the classpath attribute under JUnit, I get a different error message about needing the junit jar on the classpath, so I think JUnit is getting invoked. I just don't understand what its error is here. I've tried putting static block code in the class to do a System.out.println() when the class is loaded, and it does not appear, so there seems to be something I'm doing wrong in the configuration.
Can someone please tell me what's wrong here?
EDIT:
directory structure:
JUnit1
--bin
--test
--SimpleJUnitTest
--lib
--junit.jar
--scripts
--build.xml
--src
--tst
--test
--SimpleJUnitTest.java
I also copied build.xml to tst and ran it from the command line from that directory, same result.
I've copied junit.jar to %ant_home%\lib with no effect, though when I took the pathelement line out of the classpath I got the message "The for must include junit.jar if not in Ant's own classpath". I'm not sure where "Ant's own classpath" is specified. The classpath block with the new error message is this:
<classpath>
<pathelement location="c:/users/995868/apache-ant-1.9.4/lib" />
<pathelement location="../bin" />
</classpath>
I'm not using hamcrest features anywhere, so I haven't looked it up and put it in. I was trying to make a simple example, and the documentation for junit under ant (at least) does not mention that hamcrest is necessary.
I suppose you are missing hamcrest-core.jar from your ant classpath.
EDIT: and you are also missing the test file class itself from your classpath. So you need to update your classpath in the following manner:
<classpath>
<pathelement location="bin"/> <!--here is your test class-->
<pathelement location="lib/hamcrest-core-1.3.jar"/>
<pathelement location="lib/junit-4.12.jar"/>
</classpath>
Your class does not contain any testcases, which is an error. Your #Test annotation will be ignored, as you have not specified an #RunWith that will actually use it, so JUnit searches for methods named "test...".
So you have two choices:
a) Rename your method to "testSomething" or similar.
b) Add #RunWith(BlockJUnit4ClassRunner.class) above your class definition
Both ways will ensure that at least one test exists in your class, either via naming convention (a) or via annotion (b).
I need to filter java files before compilation, leaving the original sources unchanged and compiling from filtered ones (basically, I need to set build date and such).
I'm using NetBeans with its great Ant build-files.
So, one day I discovered the need to pre-process my source files before compilation, and ran into a big problem. No, I did not run to SO at once, I did some research, but failed. So, here comes my sad story...
I found the "filter" option of "copy" task, overrided macrodef "j2seproject3:javac" in build-impl.xml file and added filter in the middle of it. I got the desired result, yes, but now my tests are not working, since they use that macrodef too.
Next, I tired to overriding "-do-compile" target, copying&filtering files to directory build/temp-src, and passing an argument of new source directory to "j2seproject3:javac":
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,
-compile-depend,-prepare-sources"
if="have.sources" name="-do-compile">
<j2seproject3:javac gensrcdir="${build.generated.sources.dir}" srcdir="build/temp-src"/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
And now Ant says to me, that macrodef in question does not exist!
The prefix "j2seproject3" for element "j2seproject3:javac" is not bound.
That's strange, since build-impl.xml contains that macrodef, and build-impl.xml is imported into main build file.
And, by the way, I cannot edit build-impl.xml directly, since NetBeans rewrites it on every other build.
So, my question is: how can I automatically filter sources before compiling in NetBeans, and do not break the build process?
Looking at the default build.xml, it contains a comment that reads (in part):
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
So, to inject some pre-compile processing, you would provide a definition for -pre-compile.
FWIW, the error you got is because the j2seprojectX prefix is defined on the project tag of build-impl.xml, and the code in build.xml is outside of that tag.
Since I found an answer, and because it seems that nobody knows the answer, I'll post my solution.
build.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Needed to add xmlns:j2seproject3 attribute, to be able to reference build-impl.xml macrodefs -->
<project name="Parrot" default="default" basedir="." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3">
<import file="nbproject/build-impl.xml"/>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml, -compile-depend,-prepare-sources" if="have.sources" name="-do-compile">
<j2seproject3:javac gensrcdir="${build.generated.sources.dir}" srcdir="build/temp-src"/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<!-- target to alter sources before compilation, you can add any preprocessing actions here -->
<target name="-filter-sources" description="Filters sources to temp-src, setting the build date">
<delete dir="build/temp-src" />
<mkdir dir="build/temp-src" />
<tstamp>
<format property="build.time" pattern="yyyy-MM-dd HH:mm:ss"/>
</tstamp>
<filter token="build-time" value="${build.time}" />
<copy todir="build/temp-src" filtering="true">
<fileset dir="src">
<filename name="**/*.java" />
</fileset>
</copy>
</target>
</project>
I`m trying to remove some package from my report and having trouble.
Could some one give me some help?
I'm using EMMA in my ant process.
<!-- Generate the emma report both in xml and html -->
<emma>
<report
sourcepath="${build.report.src}"
metrics="class:${coverage.classes.min},method:${coverage.methods.min}">
<fileset dir="${build.report.junit.data.dir}">
<include name="*.emma"/>
</fileset>
<html outfile="${build.report.reports}/emma/raw.html" depth="method"/>
<xml outfile="${build.report.tmp}/emma.xml" depth="method"/>
</report>
</emma>
I`ve tried to use:
<filter excludes="com.my.package.*"/>
But with no success :(
Emma allows the use of filters at instrumentation phase to specify a set of files that need to be instrumented. In contrast you are trying to do this at report generation phase. The link given above describes how to define the instrumentation set.
I've used filters like this:
<property name="emma.filter" value="-*.unittest.* -*.unittests.* -*.TST* -*TestCase -*Test -*TestSuite" />
<emma>
<instr instrpath="${build.dir}"
mode="overwrite"
metadatafile="${build.dir}/coverage.em"
filter="${emma.filter}" />
</emma>
You can also use nested <filter> elements under <instr>
I assume you've tried all of the variations in the documentation...?
If so, I expect that you may have a typo, or something like that. Can you provide the code you're using with the exclude syntax that doesn't work, and the header of the source file for the class that is incorrectly being included?
Is there a way to exclude code from inclusion into Cobertura coverage reports? We have some methods that should not be included in the coverage report and therefore not drive down the coverage numbers.
I know that Clover has such a functionality, but I have not found anything similar for Cobertura.
You can exclude classes from instrumentation. Then they should not appear on reports. See exclude statements below.
You can also ignore calls to some methods. See ignore statement below.
If you are using maven, see maven plugin manual.
<configuration>
<instrumentation>
<ignores>
<ignore>com.example.boringcode.*</ignore>
</ignores>
<excludes>
<exclude>com/example/dullcode/**/*.class</exclude>
<exclude>com/example/**/*Test.class</exclude>
</excludes>
</instrumentation>
</configuration>
And for ant see this.
<cobertura-instrument todir="${instrumented.dir}">
<ignore regex="org.apache.log4j.*" />
<fileset dir="${classes.dir}">
<include name="**/*.class" />
<exclude name="**/*Test.class" />
</fileset>
<fileset dir="${jars.dir}">
<include name="my-simple-plugin.jar" />
</fileset>
</cobertura-instrument>
This has been breaking my head for some time now.
My problem was that I had the cobertura maven plugin setup in the reporting section instead of the build section.
The instrumentation settings, and hence the excluding of classes or packages, won't be applied if you don't set it up on build section, so watch out for this.
Remember to exclude inner classes too.
<exclude>path/to/class/MyClass*.class</exclude>
It took me ages to notice I was missing an asterisk!
Cobertura doesn't currently provide such a feature, and neither does Emma (which we use) although it is listed as a forthcoming enhancement - although in the form of an extension to the exclusion rules I believe rather than as an annotation.
Would be handy to cover off those few inaccessible corners cleanly so that you can strive for 100% without being ridiculous.
I think annotations would probably be a friendlier way to do it, but they ought to be fairly explicitly named and based on a list of acceptable scenarios as I fear otherwise something like '#ExcludeFromCoverage' would get added over generously.
Since 2.0 you can write your own #CoverageIgnore annotation.
It will be recognized by Cobertura, which will avoid considering annotated methods (does not work on classes as far as I know).
Create an empty annotation:
public #interface CoverageIgnore {}
Then annotate the methods you want to exclude from the reports:
public class SomeClass {
#CoverageIgnore
public void foo(String baz) {
// useless stuff
}
}
Source: https://github.com/cobertura/cobertura/wiki/Coverage-Annotations