Why does Cobertura seem to switch my Eclipse's Java version? - java

These are the steps that create the error:
Run my unit tests within Eclipse (Cntrl-F11). All 67 succeed and report as such.
Using an Ant build.xml file, run a Cobertura task to generate a coverage report. The task fails stating that a unit test has failed.
When I try to run the unit tests using Eclipse again, I receive the following error:
Unsupported major.minor version 51.0
(These symptoms persist until I use Project -> Clean within Eclipse.)
My Cobertura ant task is:
<target name="report-test" description="Generate a test coverage report." depends="clean, compile">
<taskdef resource="tasks.properties">
<classpath>
<pathelement location="${lib.dir}/cobertura-1.9.4.1/cobertura.jar" />
<pathelement location="${lib.dir}/cobertura-1.9.4.1/lib/asm-3.0.jar" />
<pathelement location="${lib.dir}/cobertura-1.9.4.1/lib/asm-tree-3.0.jar" />
<pathelement location="${lib.dir}/cobertura-1.9.4.1/lib/log4j-1.2.9.jar" />
<pathelement location="${lib.dir}/cobertura-1.9.4.1/lib/jakarta-oro-2.0.8.jar" />
</classpath>
</taskdef>
<cobertura-instrument todir="${build.dir}/cobertura-instrument">
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
<junit printsummary="yes" fork="true" haltonfailure="yes" showoutput="yes">
<classpath location="${build.dir}/cobertura-instrument"/>
<classpath location="${build.dir}"/>
<classpath refid="classpath.test" />
<sysproperty key="net.sourceforge.cobertura.datafile" file="cobertura.ser"/>
<formatter type="xml" />
<batchtest todir="doc/junit">
<fileset dir="${test.dir}" />
</batchtest>
</junit>
<cobertura-report srcdir="${src.dir}" destdir="doc/coverage" format="xml" />
<delete file="cobertura.ser"/>
</target>

Coberatura hasn't switched Eclipse's Java version.
What it has actually done is recompile the classes using a version of Java that is more recent than the one you are using to run Eclipse. Eclipse can't load those .class files.
The short term solution is to get Eclipse to clean and rebuild the project(s) after running Coberatura ... as you are currently doing.
In the long term, you should either change Eclipse to run using the same Java version as your Ant builds, or change the Ant build file so that it doesn't write the ".class" files into the Eclipse workspace. Or both ... 'cos having something else writing stuff into the Eclipse workspace is going to cause other problems too.

Related

Travis CI With Ant Build, Not Finding JUnit

I'm trying to figure out how to get Travis CI working with my little Java library on Github.
The problem seems to be that whenever the build process gets to the compilation stage, it won't compile the unit tests because it can't seem to find the JUnit jar file. Of course the Ant script works beautifully on my own computer, but I can't get the classpath right on Travis. How am I supposed to know where (or even if) they installed JUnit?
Here's my Ant script:
<project>
<target name="test">
<delete dir="build" />
<mkdir dir="build" />
<javac includeantruntime="false" srcdir="src" destdir="build" />
<javac includeantruntime="false" srcdir="tests" destdir="build" classpath="/usr/share/java/junit.jar" />
<junit printsummary="on">
<classpath>
<pathelement location="build" />
<pathelement path="/usr/share/java" />
</classpath>
<test name="FactorizeTest" />
</junit>
</target>
</project>
Here's the project link, notice the pretty "build failing" icon. Yay.
https://github.com/The-Craw/PrimeFactorizer
And finally here's the link to the build output. You can also get this from clicking the build icon.
https://travis-ci.org/The-Craw/PrimeFactorizer
You need the junit.jar on your classpath. (I think that is in Ant's lib directory on your locale machine).
You may have a look at the project template https://github.com/mplacona/java-junit-template-project

No runtime coverage using emma, junit and ant

I have the following project structure:
src/com/dummy/abc.java
src_tests/come/dummy/abcTest.java
build.xml
I need to check the coverage of my code done by tests using emma.
From reading the emma + junit examples i came to a conclusion that to get a report i need to do the following:
compile 'src'
compile 'src_tests'
instrument compiled 'src_tests' => 'instrumented_src_tests'
run junit on 'instrumented_src_tests' with additional jvmarg
The problem is that the step 4 should return some kind of a file which then used with 'report' command should create a report. I'm getting
emma-report:
[report] processing input files ...
[report] 1 file(s) read and merged in 67 ms
[report] nothing to do: no runtime coverage data found in any of the data files
~ edit
i'm attaching my build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="HELL scream" default="all" basedir=".">
<property name="build.sources.dir" location="${basedir}/src"/>
<property name="build.sources.des" location="${basedir}/bin/classes"/>
<property name="test.sources.dir" location="${basedir}/src_test"/>
<property name="test.sources.des" location="${basedir}/bin/classes_test"/>
<property name="test.reports.des" location="${basedir}/reports-junit"/>
<property name="emma.sources.des" location="${basedir}/bin/classes_emma"/>
<property name="emma.reports.des" location="${basedir}/reports-emma"/>
<property name="emma.final.reports.des" location="${basedir}/reports-emma/final"/>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<path id="emma.lib" >
<fileset dir="/home/user1/Desktop/emma-2.0.5312/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef resource="emma_ant.properties" classpathref="emma.lib" />
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="clean-all">
<delete failonerror="false">
<fileset dir="${emma.final.reports.des}"/>
<fileset dir="${emma.reports.des}"/>
<fileset dir="${emma.sources.des}"/>
<fileset dir="${test.reports.des}"/>
<fileset dir="${test.sources.des}"/>
<fileset dir="${build.sources.des}"/>
</delete>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="compile-sources">
<mkdir dir="${build.sources.des}"/>
<javac srcdir="${build.sources.dir}" includes="" excludes="" destdir="${build.sources.des}" listfiles="true" debug="true" includeantruntime="false"/>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="compile-tests">
<mkdir dir="${test.sources.des}"/>
<javac srcdir="${test.sources.dir}" includes="" excludes="" destdir="${test.sources.des}" listfiles="true" debug="true" includeantruntime="false">
<classpath>
<pathelement location="/home/user1/Desktop/junit-4.10.jar"/>
<pathelement location="${build.sources.des}"/>
</classpath>
</javac>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="compile-emma-tests">
<emma enabled="true" >
<instr instrpath="${test.sources.des}" destdir="${emma.sources.des}" metadatafile ="${emma.reports.des}/instrumentation.emma" merge ="true"/>
</emma>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="run-tests">
<mkdir dir="${test.reports.des}"/>
<junit haltonfailure="no" showoutput="yes" printsummary="true">
<formatter type="plain" usefile="false" />
<formatter type="xml"/>
<classpath>
<pathelement location="/home/user1/Desktop/junit-4.10.jar"/>
<pathelement location="${build.sources.des}"/>
<pathelement location="${emma.sources.des}"/>
<path refid="emma.lib" />
</classpath>
<batchtest todir="${test.reports.des}" fork="true">
<fileset dir="${emma.sources.des}"/>
</batchtest>
<jvmarg value="-Demma.coverage.out.file=${emma.reports.des}/coverage.emma" />
<jvmarg value="-Demma.coverage.out.merge=false" />
</junit>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="junit-tests-report">
<junitreport todir="${test.reports.des}">
<fileset dir="${test.reports.des}">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${test.reports.des}/junit_reports"/>
</junitreport>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="emma-tests-report">
<emma enabled="true" >
<report sourcepath="${build.sources.dir}">
<fileset dir="${emma.reports.des}" >
<include name="*.emma" />
</fileset>
<txt outfile="${emma.final.reports.des}/coverage.txt" depth="package" columns="class,method,block,line,name" />
<xml outfile="${emma.final.reports.des}/coverage.xml" depth="package" />
<html outfile="${emma.final.reports.des}/coverage.html" depth="method" columns="name,class,method,block,line" />
</report>
</emma>
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<target name="all" depends="clean-all, compile-sources, compile-tests, compile-emma-tests, run-tests, junit-tests-report, emma-tests-report"/>
</project>
it is probably something trivial...
also, when using emma.sources.dest
i'm getting this on my (only) test
run-tests:
[junit] Running com.emma.test.MathTest
[junit] Testsuite: com.emma.test.MathTest
[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0 sec
[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0 sec
[junit]
[junit] Caused an ERROR
[junit] Illegal local variable table length 5 in method com.emma.test.MathTest.<init>()V
[junit] java.lang.ClassFormatError: Illegal local variable table length 5 in method com.emma.test.MathTest.<init>()V
[junit] at java.lang.Class.forName0(Native Method)
[junit] at java.lang.Class.forName(Class.java:188)
[junit]
[junit] Test com.emma.test.MathTest FAILED
~ SOLVED
add this:
<jvmarg value="-XX:-UseSplitVerifier"/>
<jvmarg value="-Demma.coverage.out.file=${emma.reports.des}/coverage.emma" />
<jvmarg value="-Demma.coverage.out.merge=false" />
Emma hasn't had a stable release since 2005, and doesn't play well with newer versions of the JDKs. Cobertura hasn't done any new development since 2011.
Because of that, I no longer recommend to developers to use Emma or Cobertura.
I've switched to JaCoCo for code coverage. It was started by the Emma Eclipse team, and is actively being developed.
As stated in JaCoCo's mission statement.
[...]Two of the best and widely used available open source tools are EMMA and Cobertura. Both tools are not actively maintained by the original authors any more and do not support the current Java versions. Due to the lack of regression tests maintenance and feature additions is difficult.
Therefore we started the JaCoCo project to provide a new standard technology for code coverage analysis in Java VM based environments. [...]
The nice thing about JaCoCo is that it works in a wide variety of environments, and you don't have to instrument your code after compiling. The instrumentation takes place as the tests are being executed. It looks something like this:
<jacoco:coverage destfile="${target.dir}/jacoco.exec">
<junit>
[...]
</junit>
</jacoco>
You then use <jacoco:coverage> to print the coverage report.
Do you have to use Emma? If not, you might better luck getting everything working using JaCoCo.
Emma relies upon bytecode injection (if memory serves me well); but, with Java 7, the code hasn't been updated because the JVM now has a debugging interface.
JaCoCo tests code coverage by attaching to the debugging interface and listening as your code enters methods and passes over the bytecode without injecting checkpoints. It's clearly the superior way to do things (now that it exists) and I doubt that Emma will do the work to fully support Java 7.
I suggest that you "upgrade" to JaCoCo.
You get this error when you use wrong command to generate the report.
Most of the online tutorial is advocating the wrong(may by old) command, even I got this error when I used below command to generate the report:
{JAVA_HOME}\jre\lib\ext>java -cp emma.jar emma report -r html -in coverage.em, {ALFRESCO_HOME}\coverage.ec
EMMA: processing input files ...
EMMA: 1 file(s) read and merged in 60 ms
EMMA: nothing to do: no runtime coverage data found in any of the data files
Correct usage of the command is:
{JAVA_HOME}\jre\lib\ext>java -cp emma.jar emma report -r txt,html -in {JAVA_HOME}\jre\lib\ext\coverage.em -in C:\t1_tempSetup\Alfresco\coverage.ec
EMMA: processing input files ...
EMMA: 2 file(s) read and merged in 70 ms
EMMA: writing [txt] report to [{JAVA_HOME}\jre\lib\ext\coverage.txt] ...
EMMA: writing [html] report to [{JAVA_HOME}\jre\lib\ext\coverage\index.html] ...

Using Cobertura in unix to generate the code coverage reports

I m using cobertura-1.9.4.1 to generate code coverage reports.First I set the classpath to cobertura.jar and to other jars in the lib folder. Then I execute cobertura-instrument.sh.
But on executing I get the error loaded information on 0 classes . I m giving the complete path to the compiled classes still it is unable to instrument the classes .
So, what am I missing or what could be the possible reasons for this.
Do you mean the error is during the instrumentation, or that after running your tests, the coverage still shows zero?
Here's an example of instrumentation (with Ant):
<target name="--coverage.instrument">
<delete file="cobertura.ser"/>
<mkdir dir="${coverage.instrumented.dir}"/>
<cobertura-instrument todir="${coverage.instrumented.dir}">
<fileset dir="${classes.main.dir}">
<include name="**/*.class"/>
<exclude name="**/*Test.class"/>
</fileset>
</cobertura-instrument>
</target>
Don't forget that you need this sysproperty when testing (eg in Ant Junit task):
<sysproperty key="net.sourceforge.cobertura.datafile" file="cobertura.ser"/>
Once Cobertura is set up an instrumentation has happened, an example of execution:
<target name="--test.unit">
<mkdir dir="${temp.dir}/unit-tests"/>
<junit forkmode="perBatch" printsummary="yes" haltonfailure="no" haltonerror="no"
failureproperty="unit.tests.failed">
<sysproperty key="net.sourceforge.cobertura.datafile" file="cobertura.ser"/>
<classpath refid="classpath.test.utest"/>
<formatter type="xml"/>
<batchtest fork="yes" todir="${temp.dir}/unit-tests">
<fileset dir="${java.src.utest.dir}" includes="**/*Test.java"/>
</batchtest>
</junit>
</target>
I believe that recent versions of Cobertura don't work well with JDK5. Strongly suggest upgrading the JDK.

Unit test fails only when running from with Ant task

I run the same tests from both eclipse and from an Ant task. When running from eclipse all tests pass. When I run Ant junit task, one, single test fails with the following strange error:
junit.framework.AssertionFailedError
at org.eclipse.ant.internal.launching.remote.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
at org.eclipse.ant.internal.launching.remote.InternalAntRunner.run(InternalAntRunner.java:423)
at org.eclipse.ant.internal.launching.remote.InternalAntRunner.main(InternalAntRunner.java:137)
at unitests.mypackage.MyTestClass.myTestCase(Unknown Source)
What can be the cause?
I read a little and found out that it might be because eclipse and Ant use different versions of junit. In my project, junit is located at libs/junit-4.10.jar and referenced both in eclipse's .classpath file and in junit task classpath.
You can see Ant's task here:
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
<fileset dir="${src.dir}" includes="**/*.jar"/>
</path>
...
<target name="run-unit-tests" depends="compile,compile-unit-tests">
<mkdir dir="${junit.output.dir}"/>
<junit fork="yes" printsummary="yes" haltonfailure="no">
<classpath>
<path refid="classpath"/>
<fileset dir="${unit.tests.classes.dir}" includes="**/*.class"/>
</classpath>
<formatter type="xml"/>
<batchtest todir="${junit.output.dir}">
<fileset dir="${unit.tests.dir}">
<include name="**/*Test*.java"/>
</fileset>
</batchtest>
</junit>
<mkdir dir="${junit.report.dir}"/>
<junitreport todir="${junit.report.dir}">
<fileset dir="${junit.output.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${junit.report.dir}/html"/>
</junitreport>
</target>
The version of Ant is 1.7.1 and it came with eclipse.
Edit:
Eventually solved it by adding fork="yes" to junit's task. Found it by generating build file using eclipse's export option, and then looking at the differences between the generated file and mine. No idea why forking solves the problem though.
Different versions of Ant sound like a likely cause. To test that, set which Ant version you want Eclipse to use.
It's probably also a good idea to set the same version of JUnit and the same JDK that you use to run the test outside the IDE.
As the stack trace shows org.eclipse entries, I strongly suspect you are running ant via Eclipse. If you run ant from the console you will very likely not have this problem.
The cause, therefore, is a bug in Eclipse. This should be no surprise, Eclipse is full of bugs.
fork="true" helps because it causes ant to spawn a new process for execution. This new process does not have any Eclipse classes on the classpath.

Ant build fail - because ant forgets property?

I am getting the following build error-
BUILD FAILED
C:\eclipse\workspace\ContinuousTesting\build.xml:55:
C:\eclipse\workspace\ContinuousTesting\${lib.dir}
Here is the build.properties file:
src.dir=./src
build.dir=./bin
lib.dir=./lib
This is the whole task
<target name="compile" depends="properties, create.build.dir, xmlmapping.jar.import" description="Perfom compilation">
<!-- Compile the java code -->
<echo message="[compile] compiling sources with lib ${lib.dir} to ${build.dir} source dir ${basedir}" />
<javac srcdir="${src.dir}" destdir="${build.dir}" listfiles="no" debug="true" classpathref="build.classpath" fork="true" memoryInitialSize="128m" memoryMaximumSize="512m" />
<antcall target="backup" />
</target>
and it generates the following output
compile:
[echo] [compile] compiling sources with lib ./lib to ./bin source dir C:\eclipse\workspace\ContinuousTesting
[javac] Compiling 42 source files to C:\eclipse\workspace\ContinuousTesting\bin
What is my build.classpath I hear you ask....
<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
<pathelement path="${build.dir}" />
</path>
I am running this through eclipse.
What am I missing?
Thanks!
Azriel
Problem is down to the fact that classpath variable is being evaluated prior to the build.properties file being loaded.
This is resolved by not using configurable lib.dir, as it is quite constant.
thanks for your time and help

Categories