Bug 54835

Summary: Classpath use seems to be broken in junit ant task?
Product: Ant Reporter: andrew cooke <andrew>
Component: Optional TasksAssignee: Ant Notifications List <notifications>
Status: REOPENED ---    
Severity: regression CC: andrew, ashish.soni, francis.andre.kampbell, jglick, nico.kruber
Priority: P2    
Version: 1.9.7   
Target Milestone: 1.9.7   
Hardware: All   
OS: All   
Attachments: junit.jar: content
junit.jar

Description andrew cooke 2013-04-12 22:36:20 UTC
I don't fully understand the history of classpath loading, but at http://ant.apache.org/manual/Tasks/junit.html item 5 says "Leave ant-junit.jar in its default location in ANT_HOME/lib but include junit.jar in the <classpath> passed to <junit>. (since Ant 1.7)" - that appears not to work.

I have a detailed SO question at http://stackoverflow.com/questions/15979391/class-not-found-with-ant-ivy-and-junit-error-in-build-xml but to reproduce simply:

hg clone ssh://hg@bitbucket.org/isti/java-example
cd java-example
ant test

and you should see:

BUILD FAILED
/home/andrew/project/guice/hg/build.xml:33: java.lang.NoClassDefFoundError: junit/framework/TestListener
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
...
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.lang.ClassNotFoundException: junit.framework.TestListener
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
...

(the above project uses ant; alternatively copy junit-4.8.2.jar to ./lib and delete the ivy task from the build.xml).
Comment 1 andrew cooke 2013-04-12 22:40:12 UTC
Correction: "(the above project uses ant; alternatively" should be "(the above project uses IVY; alternatively..."
Comment 2 andrew cooke 2013-04-12 22:53:05 UTC
I'm not sure this is a good bug report, sorry - the details are mainly at the SO question.  If you'd prefer me to repeat them here I can do so.  Basically - I provide a classpath to the junit task, but it still gives a class not found error.
Comment 3 andrew cooke 2013-04-13 13:45:43 UTC
I am now working on this repo.  The example referred to above is tagged as "classpath problem" so to check out please do:

hg clone ssh://hg@bitbucket.org/isti/java-example
cd java-example
hg update -r "classpath problem"

Thanks, Andrew
Comment 4 andrew cooke 2013-04-13 20:13:49 UTC
Things are clearer now.  The following:

hg clone ssh://hg@bitbucket.org/isti/java-example
cd java-example
hg update -r "works with 1.8.4"
ant bootstrap test

works (gives an error because my test is missing a constructor) with Ant 1.8.4 but fails with Ant 1.9.0.

This is with a "virgin" Ant install.  The "bootstrap" copies the Ivy jar into ~/.ant/lib and then "test" downloads Junit jar to the local lib directory.

With Ant 1.8.4, having the Junit jar in the classpath for the junit task works just fine.  As documented at http://ant.apache.org/manual/Tasks/junit.html (item 5).  But with Ant 1.9.0 this code DOES NOT WORK.
Comment 5 Jesse Glick 2013-04-16 17:10:13 UTC
Michael?
Comment 6 Michael Clarke 2013-04-22 08:33:38 UTC
It looks like the class search is being delegated to the System's classloader rather than being handled by the Ant Classloader (the system Classloader has no knoweldge of JUnit since JUnit isn't on the core Ant Classpath, but is added to the JUnit task by Ivy). Given some JUnit classes must have already been loaded to have reached this point, the Ant Classloader can see the JUnit jars loaded by Ivy, but the Split Classloader seems to be delegating incorrectly when trying to load classes used by the JUnit Runner.

I suspect the list of 'split classes' in JUnitTask needs expanded to include the classes added for the @Ignore changes introduced in Ant 1.9.0. I'll do a bit more investigation on this issue to see if there are any other issues caused by JUnit being inherited from an external source rather than being in the ANTLIB directory whilst I fix this issue.

In the meantime, copying your JUnit JAR into your ANTLIB directory will allow Ant to pickup the dependent classes required to launch the JUnit task if you want to continue using Ant 1.9.0.
Comment 7 andrew cooke 2013-04-22 12:33:16 UTC
Thanks.  I've switched back to 1.8 for now (I know that I can fix it by moving jars, but the motivation is to have the build bootstrap itself completely to simplify the process for other users).
Comment 8 Michael Clarke 2013-04-22 19:27:39 UTC
Fixed under SVN revision 1470668.
Comment 9 Jesse Glick 2013-05-20 17:49:40 UTC
Looks like this bug only affected calls to <junit> with fork="false" (the unfortunate default), which should be considered deprecated as far as I am concerned; with fork="true" it is reported to work in 1.9.0.
Comment 10 George 2013-06-03 23:39:33 UTC
I'm still seeing this problem as of ant 1.9.1

I have a unit test flagged as such:

@RunWith(SpringJUnit4ClassRunner.class)

and an ant test target that contains

 <junit printsummary="yes" haltonfailure="yes" fork="true"  forkmode="once" tempdir="${report.tests.dir}">
   <classpath refid="test.classpath.run"/>

   <formatter type="plain"/>

   <batchtest fork="yes" todir="${report.tests.dir}">
     <fileset dir="${src.tests.dir}">
       <include name="**/*IntegrationTestCase*.java"/>
     </fileset>
   </batchtest>

</junit>

my classpath is built via ivy.

The ant test run does not honor the 'RunsWith' annotation.  A stack trace demonstrates this.  Running in eclipse works fine.
Comment 11 George 2013-06-03 23:55:21 UTC
Actually, I haven't the vaguest idea.  I've tried using ant 1.8.4 with and without the junit4 jar in the lib directory, as well as ant 1.9.1.  I'm flumoxed.  This may very well be my stupidity someplace.
Comment 12 George 2013-06-04 00:01:39 UTC
Totally my bad.. I didn't see that this particular case I was fiddling with extended junit3 TestCase.  Time to go shave heads.. mine and someone else's.
Comment 13 Nico Kruber 2014-03-24 16:04:46 UTC
It looks like this fix actually broke JUnit4 for me. Everything up to (and including) 1.9.0 works fine, 1.9.1-1.9.3 do not.
I created a fairly minimal test case at my git repository
https://github.com/NicoK/ant-1.9-junit

git clone https://github.com/NicoK/ant-1.9-junit.git
cd ant-1.9-junit.git
ant test

(I tested 1.9.0 by adding it to the test-lib directory and setting includeantruntime="false" for the JUnit task in the ant build file)
Comment 14 Nico Kruber 2014-03-24 16:10:38 UTC
actually, only providing ant-junit-1.9.0.jar in the test-lib folder is sufficient to make it work again
Comment 15 Michael Clarke 2015-08-29 12:44:10 UTC
Re-closing issue since it can't be replicated with the test case in #13 on a clean build of Ant 1.9.6.
Comment 16 zosrothko 2016-12-02 09:44:53 UTC
As per ant version

C:\Users\fandre\Documents\git\javacc>ant -version
Apache Ant(TM) version 1.9.7 compiled on April 9 2016

this issue is always present with the script below

		<junit printsummary="yes" haltonfailure="no">

			<classpath>
				<pathelement location="classes" />
				<pathelement location="junit" />
				<pathelement location="lib/junit.jar" />
			</classpath>

			<batchtest fork="no" todir=".">
				<fileset dir="junit">
					<include name="**/*Test.*" />
				</fileset>
				<formatter type="failure"/>
	            <!-- I want to see something ... -->
	            <formatter type="plain" usefile="false"/>
			</batchtest>
		</junit>


unittest:
   [delete] Deleting directory C:\Users\fandre\Documents\git\javacc\test.tmp
    [mkdir] Created dir: C:\Users\fandre\Documents\git\javacc\test.tmp
   [delete] Deleting directory C:\Users\fandre\Documents\git\javacc\junit
    [mkdir] Created dir: C:\Users\fandre\Documents\git\javacc\junit
    [javac] Compiling 6 source files to C:\Users\fandre\Documents\git\javacc\junit

BUILD FAILED
C:\Users\fandre\Documents\git\javacc\build.xml:229: Using loader AntClassLoader[C:\Apache Software Foundation\apache-ant-1.9.7\lib\ant-launcher.jar;C:\Apache Software Foundation\apache-ant-1.9.7\lib\ant.jar;C:\Apache Software Foundation\apache-ant-1.9.7\lib\ant-junit.jar;C:\Apache Software Foundation\apache-ant-1.9.7\lib\ant-junit4.jar;C:\Users\fandre\Documents\git\javacc\classes;C:\Users\fandre\Documents\git\javacc\junit;C:\Users\fandre\Documents\git\javacc\lib\junit.jar] on class org.apache.tools.ant.taskdefs.optional.junit.FailureRecorder: java.lang.NoClassDefFoundError: junit/framework/TestListener
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at org.apache.tools.ant.AntClassLoader.findBaseClass(AntClassLoader.java:1407)
        at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1085)
        at org.apache.tools.ant.util.SplitClassLoader.loadClass(SplitClassLoader.java:58)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at org.apache.tools.ant.taskdefs.optional.junit.FormatterElement.createFormatter(FormatterElement.java:287)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeInVM(JUnitTask.java:1617)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:1021)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:2105)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:832)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:435)
        at org.apache.tools.ant.Target.performTasks(Target.java:456)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1405)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
        at org.apache.tools.ant.Main.runBuild(Main.java:854)
        at org.apache.tools.ant.Main.startAnt(Main.java:236)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:285)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:112)
Caused by: java.lang.ClassNotFoundException: junit.framework.TestListener
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 49 more
Comment 17 zosrothko 2016-12-02 09:52:55 UTC
Created attachment 34497 [details]
junit.jar: content
Comment 18 zosrothko 2016-12-02 10:00:26 UTC
Created attachment 34498 [details]
junit.jar
Comment 19 zosrothko 2016-12-04 10:31:13 UTC
Wjunit classpath resolution for junit.jar is working with ant 1.9.3.

Did not test with 1.9.4 or 1.9.5 or 1.9.6.
Comment 20 zosrothko 2016-12-04 13:49:22 UTC
Wjunit classpath resolution for junit.jar is working with ant 1.9.3.

Did not test with 1.9.4 or 1.9.5 or 1.9.6.