Running junit ant-task without build.xml - java

I'm trying to work out how I can run an ant task without actually needed a build.xml.
In particular I want to run a JUnit task with a formatter. In xml format this looks like below:
<junit printsummary="true" errorProperty="test.failed" failureProperty="test.failed">
<classpath refid="run.class.path" />
<!-- console log -->
<formatter type="xml" classname="be.x.SFFormatter" />
<test name="be.x.SF" outfile="result" todir="${build.output.dir}" />
</junit>
It works when running the ant script, but I would like to get my app running as a runnable jar.
Running the tests from Java was easy:
JUnitCore junit = new JUnitCore();
testResult = junit.run(SeleniumFramework.class);
However, I struggle to work out how to actually get the formatter to work.
The formatter is of type org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter so I doubt I can just plug it in somewhere without running ant.
Has anyone done something similar before?
Thanks!

Ant doesn't do any magic. All it does is read the XML file, create the beans specified in it and then execute the methods as per the Task API (org.apache.tools.ant.Task).
So all you need is to do the same in your code. Don't forget to create a Project :-)

You may use Ant via Groovy to avoid the xml syntax.
See => Using Ant from Groovy for details.

Related

Is there a way to tell whether a JUnit test is being run from Ant?

I want to recognize at runtime whether my JUnit tests are being run from ant or not. The reason for this is, if it's being run from ant, I want to log information to a log file, else I just want to write to standard out.
Ant's built in JUnit Task has a showoutput attribute which will send any output produced from the tests to ant's logging system.
See also this SO question ant junit task does not report detail about reporting options.
One way to accomplish this would be to include a property in the junit task in the Ant script:
<junit fork="yes">
<jvmarg value="-Druntime.agent=ANT"/>
...
</junit>
Then, in your JUnit test harness inquire about the existence and/or property for that property:
String agent = System.getProperty("runtime.agent");
if ("ANT".equals(agent)) {
// set up file logging
} else {
// set up STDOUT logging
}

Adding extra information in JUnit reports

I am using JUnit4 and want to put some extra information to be displayed in JUnit reports.
For this, I shall be dumping the extra information to the report xml and then modify the xslt to read that extra information to generate the HTML report.
Steps so far that are working are:
Copied all the code from XMLJUnitResultFormatter to MyFormatter.java and modified the endTest() method to add that extra information in the form of an extra attribute to testcase XML tag.
This is really bad :( but I could not simply override it as there usages of the private instance variables directly without getters/setters in endTest() method.
My junit ant task:
<junit fork="yes" printsummary="withOutAndErr">
<!--<formatter type="xml"/>-->
<formatter classname="com.some.junit.MyFormatter" extension=".xml"/>
<test name="com.some.source.MyTestClassTest" todir="${junit.output.dir}"/>
<classpath refid="JUnitProject.classpath"/>
</junit>
Modified the xslt to read the extra attribute of TESTCASE xml tag and display in report.
My modified ant task for report:
<target name="junitreport" depends="MyTestClassTest">
<junitreport todir="${junit.output.dir}">
<fileset dir="${junit.output.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report styledir="reportstyle" format="frames" todir="${junit.output.dir}"/>
</junitreport>
</target>
I came across using TestNG nor SureFire Maven plugins as solutions, but I can't use them in my project.
Is there any better way than this in JUnit4?
Maybe?
The interface org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter is what needs to be implemented for a custom output format. This could write to any output stream, which is all the extensiblity that was built into the framework. You are right, there isn't a good way to extend the capabilities of XMLJUnitResultFormatter to customize the output. A copy-paste-modify certainly isn't ideal, but certainly acceptable.
Another approach might be to have more than one formatter defined in your ant task. One could be the regular xml formatter, with another being your custom one for additional information. These two files could be combined and then turned into HTML using xsl transforms.
I leave it to you to decide if this a better method than you had devised.

Findbugs & Ant - Stop the build for particular violation

I am building my application using ANT and I am checking my code for any Findbugs violations.
Now, my objective is to stop the build whenever my code contains particular findbug violation.
Is this possible using ANT & Findbugs?
N.B. Preferably not to write to any custom class.
Use the warningsProperty attribute on your findbugs task to set a property for any warnings:
<findbugs ... warningsProperty="findbugsFailure"/>
and fail task if warnings are produced:
<fail if="findbugsFailure">
For example:
<property name="findbugs.home" value="/export/home/daveho/work/findbugs" />
<target name="findbugs" depends="jar">
<findbugs home="${findbugs.home}"
output="xml"
outputFile="bcel-fb.xml"
warningsProperty="findbugsFailure">
<auxClasspath path="${basedir}/lib/Regex.jar" />
<sourcePath path="${basedir}/src/java" />
<class location="${basedir}/bin/bcel.jar" />
</findbugs>
<fail if="findbugsFailure">
</target>
An alternative idea (and worth the effort) would be to integrate Sonar into your ANT build process.
Sonar integrates Findbugs (and checkstyle and PMD) and you can centrally configure it to fail the build against any set of criteria using it's build breaker plugin. See:
How do I make Hudson/Jenkins fail if Sonar thresholds are breached?

Change working directory in ant junit task

I have a ant file that runs JUnits tests. These tests rely on a relative path to certain configuration files. I've tried to set the working directory for the batch test, but fail.
I want the working directory to be ${plugins.dir}/${name}
The JUnit part of the ant script:
<junit haltonfailure="no" printsummary="on" fork="true" showoutput="true" dir="${plugins.dir}/${name}">
<jvmarg value="-Duser.dir=${plugins.dir}/${name}"/>
<classpath>
<path refid="project.classpath"/>
<pathelement location="${plugins.dir}/${dependency}/#dot/"/>
<pathelement location="${plugins.dir}/${name}/" />
</classpath>
<formatter type="xml" />
<sysproperty key="basedir" value="${plugins.dir}/${name}"/>
<sysproperty key="dir" value="${plugins.dir}/${name}"/>
<batchtest todir="${junit.output}">
<fileset dir="${dir}">
<include name="**\*AllTests.class" />
</fileset>
</batchtest>
</junit>
I've googled and searched but the workarounds I've found have been to set the "dir", "sysproperty" or "jvmarg". As you can see I've tried them all :)
Is there a way to print the current dir in the tag? It doesnt support . That would allow me to verify if the dir is actually changed and to what.
One wildcard in this equation is that this is being run in Hudson that starts upp an eclipse process that starts antrunner. This is so we can run both junit and eclipse plugin junit tests. Shouldn't have anything to do with the problem I think.
I think you are right with setting the basedir property (see projects attributes). However, since it is a property of ANT (and not of the JVM) it is READ ONLY!
Does it effect other target if you set the basedir when calling your ant task? See Command Line reference.
ant -Dbasedir=somedir
Alternatively, span a new ant process to call your junit target. See the AntCall task or Ant task. Following examples assumes that the junit target contains your junit task. I used this task for other properties (never needed the basedir property so far.
<antcall target="junit">
<param name="basedir" value="${plugins.dir}/${name}"/>
</antcall>
<ant dir="${plugins.dir}/${name}" target="junit" />
I had the same scenario and in my case I saw that dir="...." is ignored if run in same jvm so I simply added fork='true' and it worked.
Quote from Apache's documentation site "dir - The directory in which to invoke the VM. Ignored if fork is disabled.". More here.
I'm using NetBeans. When I add to Ant properties (from Tools, Options, Java, Ant) work.dir=C:/MyWorkingDir/ it executes ant with the following command and changes the working dir to C:\MyWorkingDir:
ant -f D:\\workspace\\lib\\project -Dfork=true -Djavac.includes=com/myapp/MyTest.java -Dtest.includes=com/myapp/MyTest.java "-Dwork.dir=C:/MyWorkingDir/" test-single

junit test suites

I have a script(test.bat) that allows me to launch one java test by command line :
-java -cp() org.junit.runner.JUnitCore package.Class
Now I want to do the same for several java tests ?
how could I do it? should I have to add the byte code for each java test?
could I have an example , please?
You can use Ant to run your tests with a single command with the junit ant task. Here's an example on how to use it:
<target name="runtests" depends="clean,compiletests">
<junit printsummary="yes" haltonfailure="no">
<classpath>
<path refid="test.classpath" />
<pathelement location="${test.classes}"/>
</classpath>
<formatter type="xml"/>
<batchtest fork="yes" todir="${test.reports}">
<fileset dir="${test.src}">
<include name="**/*Test*.java"/>
</fileset>
</batchtest>
</junit>
</target>
That target uses batchtest which is part of the junit ant task. It sets your test classpath so all your tests that contain the Test.java pattern in their class name will be included. Check out the JUnit Task documentation.
In JUnit, you can group your tests into a test suite and then run that with a single command.
Here is a tutorial on using test suites in JUnit 3, and here is an SO post about same with JUnit 4. Moreover, here is a tutorial on how to use the new features of JUnit 4.
However, if you are practically trying to write a build script in your batch file, I recommend using an existing build system instead, be it Ant, Maven, Buildr or something else.
A convention used in JUnit is to have an AllTests test suite that groups all tests in the project together and have an Ant script or whatever execute the AllTests test suite.
You can create a set of suites using the JUnit annotation syntax. I describe it in more detail here.
I see 3 possibilities:
Use ant (see other answers while I'm typping)
update your batch to java -cp ... file1 file2 filen
use something like this:
org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);
public class GlobalTest { }

Categories

Resources