tags:

views:

307

answers:

2

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}"/>
    </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/9LCtNQUq


UPDATE

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?

A: 

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.

Yishai
Did that, all of my tests are still failing :(
TK Kocheran
I just edited the post with a link to my buildfile and a link to my properties file so you can get a feel for what the project layout looks like. I also gave a brief description of my directory layout as well. Thanks so much for your help.
TK Kocheran
@rfkrocktk, I think @Bert F figured it out.
Yishai
+1  A: 

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 pathelements. 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.

Bert F
Thanks a lot! Unfortunately, I'm still having the issue, but I did find a workaround. I have to manually include junit and ant-junit.jar, but it works. I'll update the post above to include this.
TK Kocheran
A couple of my tests are still throwing ClassNotFoundExceptions when trying to load classes that I know exist and are definitely on the classpath. Did I do something wrong?
TK Kocheran
@rfkrocktk - If I'm understanding you, if your first comment, you made the changes I recommended and you are still having "the issue" you originally posted - that com.mypackage.MyTestCase class was not found? But then by adding junit.jar and ant-junit.jar to the junit classpath fixed it? I guess that might make sense if MyTestCase was deriving from JUnit classes, but I don't get why the compile didn't fail if the junit classes were missing in the first place.
Bert F
Yes, I made the recommended changes, but ant was throwing an error telling me that it needed junit on the classpath. So I added junit to the classpath and then I ran it. Unfortunately, some of my tests are failing saying they can't get classes that are defined on my path. It's really weird for sure. It'll compile just fine but as soon as I try to run the tests, everything goes weird. I've never had problems like this with JUnit.
TK Kocheran
@rfkrocktk - okay, thanks for the clarification. I just wanted to make sure I was not reading the problem wrong. The above changes were correct in that they addressed the original posted problem (class not found), but then there were subsequent problems (junit missing). I'm glad the answer helped.
Bert F