Ant + JUnit = ClassNotFoundExceptions when running tests?
I'm trying to run some tests in Ant presently using JUnit, and all of my tests are failing with the following stacktrace:
java.lang.ClassNotFoundException: com.mypackage.MyTestCase
It doesn't make too much sense to me. I'm first compiling my test cases using <javac>
, then directly running the <junit>
task to run the tests. My buildfile looks like this:
<target name="compile.webapp.tests" depends="compile.webapp">
<javac srcdir="${test.java.src.dir}"
destdir="${test.java.bin.dir}">
<classpath>
<filelist>
<file name="${red5.home}/red5.jar"/>
<file name="${red5.home}/boot.jar"/>
<file name="${bin.dir}/${ant.project.name}.jar"/>
</filelist>
<fileset dir="${red5.lib.dir}" includes="**/*"/>
<fileset dir="${main.java.lib.dir}" includes="**/*"/>
<fileset dir="${test.java.lib.dir}" includes="**/*"/>
</classpath>
</javac>
</target>
<target name="run.webapp.tests" depends="compile.webapp.tests">
<junit printsummary="true">
<classpath>
<filelist>
<file name="${red5.home}/red5.jar"/>
<file name="${red5.home}/boot.jar"/>
<file name="${bin.dir}/${ant.project.name}.jar"/>
</filelist>
<fileset dir="${red5.lib.dir}" includes="**/*.jar"/>
<fileset dir="${main.java.lib.dir}" includes="**/*.jar"/>
<fileset dir="${test.java.lib.dir}" includes="**/*.jar"/>
<fileset dir="${test.java.bin.dir}" includes="**/*.class"/>
</classpath>
<formatter type="xml"/>
<batchtest todir="${test.java.output.dir}">
<fileset dir="${test.java.bin.dir}" includes="**/*TestCase*"/>
</batchtest>
</junit>
<junitreport>
<fileset dir="${test.java.output.dir}" includes="**/*"/>
<report todir="${test.java.report.dir}&q开发者_如何学编程uot;/>
</junitreport>
</target>
This is really weird, I can't seem to fix this. Is there something I'm doing wrong here? My project's directory layout looks somewhat like this:
${basedir}/src/test/java # this is "test.java.src.dir"
${basedir}/build/test/java # this is "test.java.bin.dir"
${basedir}/lib/main/java # this is "main.java.lib.dir"
${basedir}/lib/test/java # this is "test.java.lib.dir"
${basedir}/build/test/junit # this is "test.java.output.dir"
My complete buildfile is available here: http://pastebin.com/SVnciGKR
My properties file is available here: http://pastebin.com/9LCtNQUqUPDATE
By modifying my targets to look like below, I was able to get things working. Unfortunately, I have to manually embed ant-junit.jar and junit.jar into my repository, but it works, so I guess this solves it. If anyone can help me get rid of the need to embed ant-junit.jar and junit.jar, I'd really appreciate it:
<path id="webapp.tests.path" >
<pathelement location="${red5.home}/red5.jar"/>
<pathelement location="${red5.home}/boot.jar"/>
<pathelement location="${bin.dir}/${ant.project.name}.jar"/>
<pathelement path="${red5.lib.dir}"/>
<pathelement path="${main.java.lib.dir}"/>
<pathelement path="${test.java.lib.dir}"/>
</path>
<target name="compile.webapp.tests" depends="compile.webapp">
<javac srcdir="${test.java.src.dir}"
destdir="${test.java.bin.dir}">
<classpath refid="webapp.tests.path"/>
</javac>
</target>
<target name="run.webapp.tests" depends="compile.webapp.tests">
<junit printsummary="true">
<classpath>
<path refid="webapp.tests.path"/>
<pathelement location="${test.lib.dir}/ant/ant-junit.jar"/>
<pathelement location="${test.lib.dir}/ant/junit-4.8.2.jar"/>
<pathelement path="${test.java.bin.dir}"/>
</classpath>
<formatter type="xml"/>
<batchtest todir="${test.java.output.dir}">
<fileset dir="${test.java.bin.dir}" includes="**/*TestCase*"/>
</batchtest>
</junit>
<junitreport todir="${test.java.report.dir}">
<fileset dir="${test.java.output.dir}" includes="**/*"/>
<report todir="${test.java.report.dir}"/>
</junitreport>
<delete file="${test.java.report.dir}/TESTS-TestSuites.xml"/>
</target>
If I don't include the jars in the classpath, I get errors telling me that junit.jar must be on the classpath in order to run the <junit>
task. Weird, huh?
According to the ANT documentation for JUnit Task you have to do one of the following options to get junit tests to run as there is a dependency on an the junit.jar which is external to ANT:
Note: You must have junit.jar available. You can do one of:
- Put both junit.jar and ant-junit.jar in ANT_HOME/lib.
- Do not put either in ANT_HOME/lib, and instead include their locations in your CLASSPATH environment variable.
- Add both JARs to your classpath using -lib.
- Specify the locations of both JARs using a element in a in the build file.
- Leave ant-junit.jar in its default location in ANT_HOME/lib but include junit.jar in the passed to <junit>. (since Ant 1.7)
I have verified that #1, putting junit.jar in ANT_HOME\lib worked (ant-junit.jar was already there, ANT 1.8.0) and I did not need to specify a junit.jar in the classpath for the JUNIT tag. Essentially you took option #5.
I think this is the problem:
<junit printsummary="true">
<classpath>
...
<fileset dir="${test.java.bin.dir}" includes="**/*.class"/>
</classpath>
I believe the classpath shouldn't be including the .class files directly, just the root of the bin dir.
<junit printsummary="true">
<classpath>
...
<pathelement path="${test.java.bin.dir}"/>
</classpath>
A good way to debug this is to run your build verbosely and examine the classpath closely to verify it is set how you expect it to be set. See Ant command-line options -verbose
and possibly -debug
.
I'm surprised to set classpath set with only fileset
and file
elements, instead of pathelement
s. Take a look at the Ant manual on Path-like Structures for examples to see what I mean.
Finally, the duplication between the classpaths in javac
and junit
may cause problems in the future. You'll likely want to name certain paths or collection of paths so you won't be duplicating them. See Ant manual on References.
You need to reference ${test.java.bin.dir} in your junit task classpath.
Edit: Hmm, if by "still failing" you mean with the same error, then my next guess is that something must be messed up about where the root directory is relative to where the packages start, but I need to know more about your directory structure to be sure.
精彩评论