I am trying to migrate my test suite from Junit4 to Junit5. Have a bunch of System Properties given as parameters in the older targets which run tests on Junit4 but now as i am migrating to Junit5, JunitLauncher doesn't support this parameter .
Older Target which runs tests on Junit4:
<target name="test">
<mkdir dir="${junit_reports.dir}" />
<junit printsummary="${junit.printsummary}" haltonfailure="${junit.haltonfailure}" haltonerror="${junit.haltonerror}" showoutput="${junit.showoutput}" fork="true" forkmode="once" failureProperty="failed">
<sysproperty key="clover.initstring" value="${clover.dbdir}/${clover.dbfile}" />
<sysproperty key="rules.location" value="${classes.dir}/rules/impl" />
<classpath>
<path refid="classes.classpath" />
<path refid="test.classpath" />
<pathelement path="${basedir}/../../.." />
<pathelement path="${test.classes.dir}" />
<path location="${basedir}/../common/target/test_classes" />
<pathelement location="${3rdparty.dir}/prime-server-framework/framework-core-mock.jar" />
</classpath>
<formatter type="${unittest.output.type}" />
<batchtest fork="true" todir="${junit_reports.dir}">
<fileset dir="${test.classes.dir}" includes="${tests.patternset}" />
</batchtest>
</junit>
</target>
New Target which runs tests on Junit5:
<target name = "sampletest">
<mkdir dir="${junit_reports.dir}" />
<junitlauncher>
<classpath>
<path refid="classes.classpath" />
<path refid="test.classpath" />
<pathelement path="${basedir}/../../.." />
<pathelement path="${test.classes.dir}" />
<path location="${basedir}/../common/target/test_classes" />
</classpath>
<!--<testclasses outputdir="${junit_reports.dir}">
<fileset dir="${test.classes.dir}">
<include name = "**/*Test.class"/>
</fileset>
</testclasses>-->
<test name = "impl.RulesEngineValidationTest"/>
</junitlauncher>
</target>
How do i give system properties in new target?
Ant 1.10.4 does support JUnit 5. However, it does not support all the features that Ant integration JUnit 4 does. In particular, it does not support forking the junit process and therefore passing system properties.
I found this question because I was trying to do the same thing. I found a workaround though. You can set the system properties in code before calling junitlauncher.
This code is what I used to set a single system property for file encoding. You could do something similar for your properties.
<script language="javascript">
<![CDATA[
var imports = new JavaImporter(java.lang.System);
imports.System.setProperty('file.encoding', 'ISO8859_1')
]]>
</script>
Yours is a little more complicated since your properties use others. You can read an Ant variable from inside the code. (I don't know how to read one with a dot in the name so I got rid of the dot in this example)
<property name="cloverdbdir" value="clover-dir-property-value" />
<property name="cloverdbfile" value="clover-db-file-property-value" />
<script language="javascript">
<![CDATA[
var imports = new JavaImporter(java.lang.System);
imports.System.setProperty('clover.initstring', cloverdbdir + '/' + cloverdbfile);
print(imports.System.getProperty('clover.initstring'));
]]>
</script>
There are a few things to be aware of if you use this technique:
Nashorn is deprecated for removal. It is definitely in Java 11. However, it isn't guaranteed to all future versions. It seems likely that Ant will add the system property functionality natively by then so I'm not worried about it.
The system property remains set for the remainder of the build. This doesn't look like a problem for you. If it is, you'd need another script block after calling JUnit to null it out.
Related
I'm trying to create an ant script to run pitest to be able to automate my mutation testing. I am getting the error:
Could not find or load main class org.pitest.mutationtest.commandline.MutationCoverageReport
This is my MutationTest.xml ant script
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="mutationCoverage" name="PhoneBook">
<property name="ECLIPSE_HOME" value="C:/Program Files/eclipse/"/>
<path id="JUnit 4.libraryclasspath">
<pathelement location="${ECLIPSE_HOME}plugins/org.junit_4.11.0.v201303080030/junit.jar"/>
<pathelement location="${ECLIPSE_HOME}plugins/org.hamcrest.core_1.3.0.v201303031735.jar"/>
</path>
<path id="PhoneBook.classpath">
<pathelement location="bin"/>
<path refid="JUnit 4.libraryclasspath"/>
</path>
<path id="pit.path">
<pathelement location="lib/pitest-1.1.4.jar" />
<pathelement location="lib/pitest-ant-1.1.4.jar" />
</path>
<taskdef name="pitest" classname="org.pitest.ant.PitestTask" classpathref="pit.path" />
<target name="mutationCoverage">
<pitest
pitClasspath="PhoneBook.path"
classPath="PhoneBook.path"
targetClasses="pbook.*"
targetTests="pbook.*"
reportDir="MutationReports"
sourceDir="src"/>
</target>
</project>
What is causing this error, and how can I fix it?
Edit: I changed pitClasspath="PhoneBook.path" to pitClasspath="pit.path" and now I have a new error:
[pitest] Exception in thread "main" org.pitest.util.PitError: Unable to load class content for org.pitest.boot.HotSwapAgent
[pitest] Please copy and paste the information and the complete stacktrace below when reporting an issue
[pitest] VM : Java HotSpot(TM) 64-Bit Server VM
[pitest] Vendor : Oracle Corporation
[pitest] Version : 25.25-b02
[pitest] Uptime : 370
[pitest] Input ->
[pitest] BootClassPathSupported : true
[pitest] at org.pitest.mutationtest.tooling.JarCreatingJarFinder.classBytes(JarCreatingJarFinder.java:124)
[pitest] at org.pitest.mutationtest.tooling.JarCreatingJarFinder.addClass(JarCreatingJarFinder.java:113)
[pitest] at org.pitest.mutationtest.tooling.JarCreatingJarFinder.createJarFromClassPathResources(JarCreatingJarFinder.java:98)
[pitest] at org.pitest.mutationtest.tooling.JarCreatingJarFinder.createJar(JarCreatingJarFinder.java:74)
[pitest] at org.pitest.mutationtest.tooling.JarCreatingJarFinder.getJarLocation(JarCreatingJarFinder.java:63)
[pitest] at org.pitest.mutationtest.tooling.EntryPoint.execute(EntryPoint.java:70)
[pitest] at org.pitest.mutationtest.tooling.EntryPoint.execute(EntryPoint.java:43)
[pitest] at org.pitest.mutationtest.commandline.MutationCoverageReport.runReport(MutationCoverageReport.java:72)
[pitest] at org.pitest.mutationtest.commandline.MutationCoverageReport.main(MutationCoverageReport.java:43)
I don't know if that is better or worse, but hopefully it will be helpful in finding the problem.
A working example of a pitest ant build is provided at
https://github.com/hcoles/pitest-ant-example
I suggest you start with this and edit it until you have a working build for your codebase.
One difference I can see is that you have not included junit on the pitest path.
Your build looks a little strange as it seems to be tied to eclipse. If you are running from the IDE why not use the eclipse plugin?
Also, if you are not tied to Ant, you might want to consider maven as an alternative.
I believe much of your problem is that you're trying to use the Eclipse generated build.xml file, which doesn't contain the mutation testing target, and the target which you've added to remedy this has some errors.
I would suggest starting with the project here and attempting to understand how it works, and then changing their build.xml file to fit your needs.
However if this doesn't work, judging from your other question, the following build.xml should work if:
You divide your files into two source directories "src" and "test"
Both src and test folders contain the package "pbook"
You change the name of your tests to end in "Test" rather than begin in it
<?xml version="1.0" encoding="UTF-8"?>
<project name="Phonebook">
<property name="classOutputDir" value="build" />
<!-- classpath for pitest and any plugins -->
<path id="pitest.path">
<!-- must currently include the test library on the tool classpath. this will be fixed in a future version-->
<pathelement location="lib/junit-4.9.jar" />
<pathelement location="lib/pitest-0.33.jar" />
<pathelement location="lib/pitest-ant-0.33.jar" />
</path>
<taskdef name="pitest" classname="org.pitest.ant.PitestTask" classpathref="pitest.path" />
<target name="clean">
<delete dir="${classOutputDir}" />
</target>
<target name="compile" depends="clean">
<mkdir dir="${classOutputDir}/classes" />
<!-- Essential that line numbers and filenames are included in order for PIT to work -->
<javac srcdir="src" includeantruntime="false" debug="true" debuglevel="source,lines" destdir="${classOutputDir}/classes" />
</target>
<!-- classpath for compiling and testing the code. Note it does not include pitest and it's dependencies -->
<path id="test.path">
<pathelement location="${classOutputDir}/classes" />
<pathelement location="${classOutputDir}/test-classes" />
<pathelement location="lib/junit-4.9.jar" />
</path>
<target name="test" depends="compile">
<mkdir dir="${classOutputDir}/test-result" />
<mkdir dir="${classOutputDir}/test-classes" />
<javac includeantruntime="false" srcdir="test" destdir="${classOutputDir}/test-classes">
<classpath refid="test.path" />
</javac>
<junit>
<classpath refid="test.path" />
<batchtest todir="${classOutputDir}/test-result">
<!-- set test classes -->
<fileset dir="test">
<include name="**/*Test.java" />
</fileset>
<formatter type="xml" />
</batchtest>
</junit>
<junitreport todir="${classOutputDir}/test-result">
<fileset dir="${classOutputDir}/test-result">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${classOutputDir}/test-result/report" />
</junitreport>
</target>
<!-- run pitest. note that the filters for tests and classes refer to package/class names, not source file named -->
<target name="pit" depends="test">
<path id="mutation.path">
<path refid="pitest.path"/>
<path refid="test.path"/>
</path>
<pitest pitClasspath="pitest.path" threads="2" classPath="mutation.path" targetTests="pbook.*" targetClasses="pbook.*" reportDir="pitReports" sourceDir="src" />
</target>
</project>
I have an Ant Build file. I added jacoco coverage task to get the coverage of my junit testcases. It says process fork failed.
<jacoco:coverage output="file" destfile="${result.exec.file}">
<!-- forkmode="perTest" printsummary="on" maxmemory="3072m" failureProperty="test.failure" haltonerror="false" includeAntRuntime="true"-->
<junit printsummary="on" fork="true">
<classpath refid="test.run.path" />
<syspropertyset>
<propertyref builtin="commandline" />
</syspropertyset>
<!-- usefile="true" -->
<formatter type="xml" usefile="true" />
<!-- failureproperty="test.failure" haltonerror="false" -->
<batchtest todir="reports/junit-xml" fork="yes">
<fileset dir="src/test/java">
<include name="**/AllTest.java" />
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<junitreport todir="${reports.dir}/junit-xml">
<fileset dir="${reports.dir}/junit-xml">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${reports.dir}/junit-html" />
</junitreport>
Have you tried this without jacoco? I ask because I'm having the same problem with fork failure and I'm not using jacoco. I also have another project's ant script doing the same thing and it works fine. Yet somehow the project and ant script I'm currently working on fails the fork. In both cases I have to have fork set to "yes" because I'm specifying an alternate jvm for the junit block.
Maybe the classpath length issue is worth exploring. I know that in my case the ant script that's failing the fork has a longer class path than the one that's working. I had another project with a longer classpath that was also failing to fork but I didn't really need to fork so I just set it to "no".
Following the example given at http://www.jooq.org/doc/2.4/manual/META/Configuration/#N10607 on how to run the jooq code-generation I ran into the problem that the build fails with the message:
codegen.xml:7: taskdef class org.jooq.util.GenerationTask cannot be found
For a reference, here is codegen.xml
<project name="..." default="generate-test-classes"
basedir=".">
<property name="path.to.jooq.distribution" value="${basedir}/libs"/>
<property name="path.to.mysql.driver" value="${basedir}/libs"/>
<property name="mysql.driver" value="mysqlcon"/>
<!-- Task definition -->
<taskdef name="generate-classes" classname="org.jooq.util.GenerationTask">
<classpath>
<fileset dir="${path.to.jooq.distribution}">
<include name="jooq.jar" />
<include name="jooqmeta.jar" />
<include name="jooqcodegen.jar" />
</fileset>
<fileset dir="${path.to.mysql.driver}">
<include name="${mysql.driver}.jar" />
</fileset>
</classpath>
</taskdef>
<!-- Run the code generation task -->
<target name="generate-test-classes">
<generate-classes jdbcurl="jdbc:mysql://localhost:3306/crawler"
jdbcuser="..." jdbcpassword="..." generatordatabaseinputschema="..."
generatortargetpackage="model.persistence.jooq"
generatortargetdirectory="${basedir}/src" />
</target>
</project>
I triple checked the definition of the classpath and every file listed exists under the given location. So what would be the problem? Am I missing something? Do I need to configure ant somewhere to recognize the task?
Since I already checked ant: failed to create task or type, I tried to move the taskdef inside the target, but to no avail.
The ant task was an example implementation in jOOQ 2.x. It has been deprecated a long time ago and removed from jOOQ 3.0:
http://www.jooq.org/notes.php?version=3.0
https://github.com/jOOQ/jOOQ/issues/1118
http://www.jooq.org/doc/3.1/manual/code-generation/codegen-configuration/#N12E23
The version of the manual that you've linked is quite outdated.
I want to define in command line what unit tests are to be run. Tests are defined in a logical structure based on Java packages. From the command line I want to define what Java packages are to be included in the test run (i.e. what tests to include).
In this way I want to loop through a tokenized list of path values, and include Java tests from these paths. However the batchtest element does not support nested for loops. How can I modify this to do what I want? So the amount of includes are as many as there are defined path values.
Updated:
I have defined target like this:
<target name="test">
<property name="path" value="**"/>
<junit fork="yes" failureproperty="true" forkmode="once">
<formatter type="xml" />
<classpath>
<pathelement path="bin.path"/>
</classpath>
<batchtest haltonerror="false" todir="${test.dir}">
<fileset dir="/src/test/">
<for list="${path}" param="path">
<sequential>
<var name="path" value="#{path}"/>
<include name="**/${path}/**/*.java" />
</sequential>
</for>
</fileset>
</batchtest>
</junit>
You could use reguler expression.
For example;
<batchtest haltonfailure="yes" todir="/test">
<fileset dir="/build/classes/"
includes="**/TestBlaBla.class" excludes="**/BlaBla.class" />
</batchtest>
I hope it helps to you.
I have a java project that has just been imported into TFS and I've been trying to get TFS to output the results of the unit tests.
At the end of the TFSBuild.proj file I have the following:
<ItemGroup>
<!-- Ant Call Configuration.
The build file called should be included in the workspace of the build definition.
-->
<AntBuildFile Include="$/PROJECT_NAME/Main/tfsbuild.xml">
<Targets>build,test</Targets>
<Properties>BinariesRoot=$(BinariesRoot);BuildDefinitionName=$(BuildDefinitionName);BuildDefinitionUri=$(BuildDefinitionUri);BuildDirectory=$(BuildDirectory);BuildNumber=$(BuildNumber);DropLocation=$(DropLocation);LogLocation=$(LogLocation);SourceGetVersion=$(SourceGetVersion);TestResultsRoot=$(TestResultsRoot);TeamProject=$(TeamProject);WorkspaceName=$(WorkspaceName);WorkspaceOwner=$(WorkspaceOwner)</Properties>
<Lib></Lib>
</AntBuildFile>
<!-- JUnit XML Results files should be created using the XML formatter
and be located in the following path
-->
<JUnitLogFiles Include="$(BinariesRoot)\**\TEST-*.xml" />
</ItemGroup>
This kicks off the build and tells TFS where to find the junit test results.
The issue is, TFS is not finding the unit test results even though I can see through the logs that the tests were run.
I almost gave up on this, and changed my ant file to produce a junit report and store it with the build artifacts. I changed my ant task to be:
<target name="test" depends="compile-tests">
<echo>Running unit tests, output should be in ${junit.output}</echo>
<junit printsummary="yes">
<classpath>
<pathelement path="${compile.classpath}" />
<pathelement path="${lib.dir}/junit-4.0.jar" />
<pathelement path="${build}" />
<pathelement path="${dist-classes}" />
</classpath>
<formatter type="xml" />
<batchtest fork="yes" todir="${junit.output}">
<fileset dir="${src.test}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
<mkdir dir="${DropLocation}/${BuildNumber}/test_results" />
<junitreport todir="${junit.output}">
<fileset dir="${junit.output}">
<include name="TEST-*.xml" />
</fileset>
<report todir="${DropLocation}/${BuildNumber}/test_results" />
</junitreport>
</target>
But after checking the output from the next build, I realised that the JUnit output was saved as TESTS-TestSuites.xml, not TEST-*.xml. I changed my TFSBuild.proj file accordingly, and now have the build results appearing in TFS.
Somehow the junitreport task still picks up the output though.