I am trying to run JUnit tests from an Ant script. The tests use the JMockit mocking framework, which for Java 5 requires specifying it as a javaagent to run correctly. Here is the script I am running:
<!DOCTYPE project>
<project name="junit_test">
<property name="PROJECT_PATH" value="{Path to my eclipse project}" />
<property name="LIB_PATH" value="${PROJECT_PATH}/WebContent/WEB-INF/lib" />
<property name="TEST_PATH" value="WebContent/WEB-INF/classes" />
<target name="run_junit">
<junit fork="yes" forkmode="once" printsummary="true">
<jvmarg value="-javaagent:${LIB_PATH}/jmockit.jar" />
<classpath path="${LIB_PATH}/jmockit.jar" />
<classpath path="${LIB_PATH}/junit-4.8.2.jar" />
<batchtest>
<fileset dir="${TEST_PATH}">
<include name="**/*Test.class"/>
</fileset>
</batchtest>
</junit>
<junitreport todir="/junitOut">
<fileset dir="/junitOut">
<include name="INCOMPLETE-*.xml"/>
<include name="TEST-*.xml"/>
</fileset>
<report todir="/junitOut/html"/>
</junitreport>
</target>
</project>
I have a feeling that I'm not setting the javaagent correctly. The tests error with this exception:
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Constructor.java:515)
at org.eclipse.ant.internal.ui.antsupport.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main(InternalAntRunner.java:137)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:140)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:140)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
Caused by: java.lang.RuntimeException: com.sun.tools.attach.AttachNotSupportedException: Unable to enqueue operation: the target VM does not support attach mechanism
at mockit.internal.startup.JDK6AgentLoader.attachToThisVM(JDK6AgentLoader.java:113)
at mockit.internal.startup.JDK6AgentLoader.loadAgent(JDK6AgentLoader.java:77)
at mockit.internal.startup.AgentInitialization.initializeAccordingToJDKVersion(AgentInitialization.java:41)
at mockit.internal.startup.Startup.initializeIfNeeded(Startup.java:203)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:200)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
Caused by: com.sun.tools.attach.AttachNotSupportedException: Unable to enqueue operation: the target VM does not support attach mechanism
at sun.tools.attach.WindowsVirtualMachine.(WindowsVirtualMachine.java:58)
at sun.tools.attach.WindowsAttachProvider.attachVirtualMachine(WindowsAttachProvider.java:58)
at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
at mockit.internal.startup.JDK6AgentLoader.attachToThisVM(JDK6AgentLoader.java:110)
Is my javaagent setting correct? If it is, what else could be causing this error?
I don't know if that's the solution, but you are not setting the classpath correctly. Try this:
<classpath>
<pathelement location="${LIB_PATH}/jmockit.jar" />
<pathelement location="${LIB_PATH}/junit-4.8.2.jar" />
</classpath>
Your jvmarg to Ant for javaagent looks correct. Are you using Java 6 or a JVM that otherwise supports the Attach API? It looks like you have to also pass -Dcom.sun.management.jmxremote to enable it for older versions of Java. I'm assuming you need it because the exception says "the target VM does not support attach mechanism".
For IBM JDK 6 it appears you need to specify -Dcom.ibm.tools.attach.enable=yes.
Related
I am using Eclipse Helios with Tomcat 7 on Windows and have imported Apache Ant-1.8.4 and works fine but I had to set up the same environment on another machine and when I attempted to build the project using Ant in Eclipse it failed with the following message;
C:\eclipsehelios\workspace\projectname\build.xml:207: Problem: failed to
create task or type emmajava
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken
place
I have had this error before and just required to ensure the build file had the correct path to the Ant folder but this didn't resolve things this time. I found by copying in the following files to the Ant's lib folder solved the problem but these were not required in my own PC and wondered if someone would tell me if this was the correct way to resolve this problem and if so why do I not require these on my own PC?
antlr-2.7.6.jar
commons-beanutils-1.8.3-javadoc.jar
commons-beanutils-1.8.3-sources.jar
commons-beanutils-1.8.3.jar
commons-beanutils-bean-collections-1.8.3.jar
commons-beanutils-core-1.8.3.jar
commons-cli-1.2-javadoc.jar
commons-cli-1.2-sources.jar
commons-cli-1.2.jar
commons-logging.jar
ganymed.jar
guava-13.0.1-sources.jar.sav
guava-13.0.1.jar.sav
guava-gwt-13.0.1-sources.jar.sav
guava-r07-javadoc.jar.sav
guava-r07-sources.jar.sav
guava-r07.jar.sav
jna.jar
svnant-1.3.1.jar
svnant.jar
svnClientAdapter.jar
svnjavahl.jar
svnkit.jar
EDIT:
If I click on the line "C:\eclipsehelios\workspace\projectname\build.xml:207" it goes to the following section of the build file with the top line "
<emmajava enabled="${emma.enabled}" libclasspathref="emma.lib"
fullmetadata="yes" filter="${emma.filter}" sourcepath="src"
classname="the.company.domain.test.EmmaLoginMain">
<classpath>
<pathelement path="test" />
<pathelement path="build/classes" />
<pathelement path="build_tests/classes" />
<pathelement path="test" />
<fileset dir="${libDir}">
<include name="**/*.jar" />
</fileset>
<fileset dir="${tomcat_lib}">
<include name="**/*.jar" />
</fileset>
<fileset dir="${test_lib}">
<include name="**/*.jar" />
</fileset>
</classpath>
<!-- regular <java> options are still available: -->
<!--<arg value="somearg" /> -->
<!-- <emmajava> option extensions [see the reference manual for
complete details]: -->
<xml outfile="${test.reports.dir}/emma/coverage.xml" />
<txt outfile="${test.reports.dir}/emma/coverage.txt" />
<html outfile="${test.reports.dir}/emma/coverage.html" />
</emmajava>
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] ...
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.
I have my own build.xml file consisting of few targets to compile and run my Java project with Ant. Here is the relevant part of this one:
<path id="libpath">
<fileset dir="${lib.dir}" includes="**/*.jar" />
</path>
<patternset id="resources">
<include name="relative/path/to/resources/" />
</patternset>
<path id="resourcespath">
<fileset dir="${src.dir}">
<patternset refid="resources" />
</fileset>
</path>
<target name="compile">
<mkdir dir="${build.dir}" />
<mkdir dir="${classes.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="libpath" includeantruntime="false" debug="true" debuglevel="lines,vars,source" />
<copy todir="${classes.dir}">
<path refid="resourcespath" />
</copy>
</target>
<target name="debug" depends="compile">
<java fork="true" classname="${main-class}">
<sysproperty key="java.library.path" path="${dist.dir}"/>
<classpath>
<pathelement location="${classes.dir}" />
<path refid="libpath" />
</classpath>
</java>
</target>
All I want to do is to debug the compiled code in ${classes.dir} using Netbeans by running the debug target of build.xml. At the moment, this target starts the compiled application without giving a chance to stop at breakpoints. I know that Netbeans generates default build-impl.xml file but this one is too large and is difficult to understand for me. That's why I want to know whether it's possible to use the Netbeans IDE to debug Java code compiled by Ant using my own build.xml file.
There is also the similar question on debugging Java code when using Ant script in Eclipse, but as I can see the solution proposed is Eclipse specific.
Method proposed by Sergey works but one have to do the following actions each time to debug a project:
Press Debug Main Project button (Ctrl+F5), Netbeans will wait for a debbuger to attach;
Choose "Debug" > "Attach Debugger..." from Netbeans main menu, specify debugger's parameters in appeared dialog and then press "OK" button or select previously used debbuger from dropdown list of toolbar's debug button (e.g. Attach to 5432);
Debug your application and then close it (Shift+F5 will not terminate the application as usual, it will only finish the debugging session).
In my opinion, the better way to use "Attach Debugger..." is to choose SocketListen connector:
Perform step 2 from the previous steps' chain (select Listen to 5432) - debugger will wait for an application to start (please note, that jvmarg's suboption server must be set to n - refer to Remote Debugging FAQ).
Press Debug Main Project button (Ctrl+F5).
Debug your application and then close it or terminate it simultaneously with debugging session by pressing Shift+F5.
Anyway, this method is also uncomfortable, especially if you were accustomed to start the debugging by simply pressing Ctrl+F5 or pressing corresponding toolbar button. Choosing required debugger from the dropdown menu everytime is annoying.
So here is the best solution - start the debugger directly from Ant's debug target. In my case it looks like this:
<target name="debug" depends="compile">
<nbjpdastart addressproperty="jpda.address" name="MyProjectName" transport="dt_socket">
<classpath>
<pathelement location="${classes.dir}" />
<path refid="libpath" />
</classpath>
</nbjpdastart>
<java fork="true" classname="${main-class}">
<sysproperty key="java.library.path" path="${dist.dir}" />
<classpath>
<pathelement location="${classes.dir}" />
<path refid="libpath" />
</classpath>
<jvmarg value="-Xdebug" />
<jvmarg value="-Xnoagent" />
<jvmarg value="-Djava.compiler=none" />
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}" />
</java>
</target>
To get more information, please, look at Creating a Target to Debug Your Java SE Application
Advises from Eclipse topic will work for you as well.
Use next JVM parameters (add them to java target call):
<jvmarg value="-Xdebug" />
<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5432" />
In netbeans use Debug->Attach Debugger with port 5432
My Ant build includes a junit task that runs some tests. In order for the tests to work, the value of the property that specifies the current working directory (user.dir) must be changed, but I am unsure how to achieve this.
The task in question currently looks like this:
<junit printsummary="withOutAndErr" fork="true"
haltonfailure="yes" showoutput="true"
filtertrace="false" dir="C:/workspace/obp-web">
<jvmarg value="-Duser.dir=C:/workspace/obp-web"/>
<classpath>
<fileset dir="${web.lib.dir}" includes="**/*.jar"/>
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</classpath>
<batchtest fork="no" todir="${web.build.dir}/testresults">
<formatter type="xml"/>
<zipfileset src="${web.build.dir}/test-obp-web.jar">
<include name="**/*Test.class"/>
</zipfileset>
</batchtest>
</junit>
Notice that I've tried to use both the "dir" attribute and the "jvmarg" task to change the working directory to C:/workspace/obp-web. However when I run Ant with verbose output turned on, I see the following output, which indicates that the working dir has not been set correctly:
[junit] dir attribute ignored if running in the same VM
[junit] Using System properties
{java.runtime.name=Java(TM) SE Runtime
Environment,
sun.boot.library.path=c:\jdk6\jre\bin,
java.vm.version=10.0-b23, ant.lib
rary.dir=C:\java\apache-ant-1.7.0\lib,
java.vm.vendor=Sun Microsystems Inc.,
java.vendor.url=http://java.sun.com/,
path.separator=;, java.vm.name=Java
HotSpot(T M) Client VM,
file.encoding.pkg=sun.io,
user.country=CA,
sun.java.launcher=SUN_STANDARD,
sun.os.patch.level=Service Pack 1,
java.vm.specification.name=Java Virtual Machine Specification,
user.dir=c:\workspace\obp-ear, java.runtime.version=1.6.0_07-b06,
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment,
java.endorse
d.dirs=c:\jdk6\jre\lib\endorsed,
os.arch=x86,
java.io.tmpdir=C:\Users\donal\AppData\Local\Temp\,
line.separator=
Use the attribute "dir" (must also fork the vm):
http://ant.apache.org/manual/Tasks/junit.html
Try using a jvmarg:
<junit fork="yes">
<jvmarg value="-Duser.dir=somedir"/>
...
</junit>
Note that fork must be true on both the junit tag and the batchtest tag as the batchtest tag overrides the value from junit. Jvmargs only work if junit forks a new JVM.
Same problem as you.
I resolved it by making the batchtest fork to true :
batchtest fork="no" ..
to
batchtest fork="yes" ..
Have you tried pathelement location? This worked for me.
<classpath>
<!-- filesets, etc. -->
<pathelement location="C:/workspace/obp-web" />
</classpath>