You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Lucas Bullen <lb...@redhat.com> on 2018/06/01 17:16:23 UTC

ClassLoaders in JUnit Launcher Task

Hello,

I'm attempting to use the JUnit 5 Platform Launcher API to upgrade our
testing process to allow for JUnit 5 tests. To minimize the required
changes in the rest of our work flow, I am planning on using Ant's
JUnitLauncherTask [1] which brought with it legacy test result formatters.
With these legacy test result formatters, no changes would have to be made
to the result processing and displaying processes.

However, when attempting to do this I run into an issue with ClassLoaders.
JUnitLauncherTask.execute() [2] sets the thread's ClassLoader to its own or
to an AntClassLoader, both of which do not contain the junit TestEngine's
which causes a Preconditions exception in the constructor of JUnit's
DefaultLauncher due to finding no Launchers [3].

Our previous way of getting around this was to create our own ClassLoader
with the required TestEngines and set this to the current thread's
ClassLoader to ensure that the TestEngines are found [4].

This technique no longer works for the JUnitLauncherTask as it resets the
ClassLoader right before executing the tests. Does anyone have a suggestion
on how to resolve this issue?

My two working plans are to either copy over the necessary files from
org.apache.tools.ant.taskdefs.optional.junitlauncher and remove it's
ClassLoader manipulation code so that I can use my own ClassLoader, or to
use reflection to access the addClass method of the JUnitLauncherTask's
ClassLoader and add our classes. First plan I know works but
copying/maintaining that much code is no good; second plan I haven't gotten
to work yet, but even if I can it is rather hacky.

[1] https://github.com/apache/ant/pull/60/
[2]
https://github.com/apache/ant/blob/342bf00579318f00b373e86a148af984bc7d6acb/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java#L71
[3]
https://github.com/junit-team/junit5/blob/6b4de716ba3b0b46c847e340e2f68954d0cc6192/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java#L54
[4]
https://git.eclipse.org/c/pde/eclipse.pde.ui.git/tree/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java?h=BETA_JUNIT5#n226

Thanks for the help or insight in advance.

-- 

Lucas Bullen

Software Engineering Intern

Red Hat

<https://www.redhat.com>

90 Eglinton Ave E #502,

Toronto, ON M4P 2Y3

lbullen@redhat.com
<https://red.ht/sig>

Re: ClassLoaders in JUnit Launcher Task

Posted by Jaikiran Pai <ja...@gmail.com>.
On 03/06/18 3:13 PM, Jaikiran Pai wrote:
> I have now added a section in the junitlauncher task's manual 

The section's titled "Using the classpath element to include test engines".

-Jaikiran

> to include an example which shows how to setup the classpath element 
> to include thetestengines. The document isn't live yet but can be 
> found in its raw form here[1].
>
> I'm not 100% sure if this is what you were after, so feel free to 
> reply with details if there's something else you are looking for.
>
> [1] 
> https://raw.githubusercontent.com/apache/ant/master/manual/Tasks/junitlauncher.html
>
> -Jaikiran
> On 02/06/18 8:39 AM, Jaikiran Pai wrote:
>> HelloLucas,
>>
>>
>> On 01/06/18 10:46 PM, Lucas Bullen wrote:
>>>
>>> However, when attempting to do this I run into an issue with 
>>> ClassLoaders.
>>> JUnitLauncherTask.execute() [2] sets the thread's ClassLoader to its 
>>> own or
>>> to an AntClassLoader, both of which do not contain the junit 
>>> TestEngine's
>>
>> Which test engine are you using and where are the jars for those 
>> located? The vintage and the jupiter test engines (part of JUnit 5) 
>> or any test engine for that matter, can be placed in the ANT_HOME/lib 
>> directory and they should be picked up. Or you can pass the -lib 
>> option while launching Ant to pass the location of those jars. These 
>> methods have been noted in the documentation of the task[1]
>>>
>>> Our previous way of getting around this was to create our own 
>>> ClassLoader
>>> with the required TestEngines and set this to the current thread's
>>> ClassLoader to ensure that the TestEngines are found [4].
>>>
>>> This technique no longer works for the JUnitLauncherTask as it 
>>> resets the
>>> ClassLoader right before executing the tests. Does anyone have a 
>>> suggestion
>>> on how to resolve this issue?
>>
>> The way JUnit 5 works, it uses the thread context classloader to find 
>> the test engines (and even test cases). That's why the 
>> JUnitLauncherTask sets it up in a manner that the right classloader 
>> is setup before executing the tests.
>>
>> I looked at the customer classloader you pointed to, in your 
>> footnotes. How was that being setup in the Ant build, previously?
>>
>> Overall, if I understand your question correctly - you do not want to 
>> add the *test engines* to the ANT_HOME/lib and neither do you want to 
>> pass the -lib option while launching Ant and instead want to define a 
>> classpath in your build file and use that classpath for finding the 
>> test engines? If that's the case, then yes it's currently a 
>> limitation (one that which Stefan had rightly brought up very early 
>> in the dev cycle of this task). I do plan to tackle this in a better 
>> way, but given the complexity involved with classloaders (both due to 
>> the nature of JUnit 5 and Ant itself) and the fact that I lost focus 
>> on this task for a bit, I haven't been able to come up with a 
>> solution. I'll look more into this in the upcoming days and see how 
>> we can improve this.
>>
>> If I misunderstood your use case, please do let us know.
>>
>> [1] https://ant.apache.org/manual/Tasks/junitlauncher.html
>>
>> -Jaikiran
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Re: ClassLoaders in JUnit Launcher Task

Posted by Jaikiran Pai <ja...@gmail.com>.
I have now added a section in the junitlauncher task's manual to include 
an example which shows how to setup the classpath element to include 
thetestengines. The document isn't live yet but can be found in its raw 
form here[1].

I'm not 100% sure if this is what you were after, so feel free to reply 
with details if there's something else you are looking for.

[1] 
https://raw.githubusercontent.com/apache/ant/master/manual/Tasks/junitlauncher.html

-Jaikiran
On 02/06/18 8:39 AM, Jaikiran Pai wrote:
> HelloLucas,
>
>
> On 01/06/18 10:46 PM, Lucas Bullen wrote:
>>
>> However, when attempting to do this I run into an issue with 
>> ClassLoaders.
>> JUnitLauncherTask.execute() [2] sets the thread's ClassLoader to its 
>> own or
>> to an AntClassLoader, both of which do not contain the junit 
>> TestEngine's
>
> Which test engine are you using and where are the jars for those 
> located? The vintage and the jupiter test engines (part of JUnit 5) or 
> any test engine for that matter, can be placed in the ANT_HOME/lib 
> directory and they should be picked up. Or you can pass the -lib 
> option while launching Ant to pass the location of those jars. These 
> methods have been noted in the documentation of the task[1]
>>
>> Our previous way of getting around this was to create our own 
>> ClassLoader
>> with the required TestEngines and set this to the current thread's
>> ClassLoader to ensure that the TestEngines are found [4].
>>
>> This technique no longer works for the JUnitLauncherTask as it resets 
>> the
>> ClassLoader right before executing the tests. Does anyone have a 
>> suggestion
>> on how to resolve this issue?
>
> The way JUnit 5 works, it uses the thread context classloader to find 
> the test engines (and even test cases). That's why the 
> JUnitLauncherTask sets it up in a manner that the right classloader is 
> setup before executing the tests.
>
> I looked at the customer classloader you pointed to, in your 
> footnotes. How was that being setup in the Ant build, previously?
>
> Overall, if I understand your question correctly - you do not want to 
> add the *test engines* to the ANT_HOME/lib and neither do you want to 
> pass the -lib option while launching Ant and instead want to define a 
> classpath in your build file and use that classpath for finding the 
> test engines? If that's the case, then yes it's currently a limitation 
> (one that which Stefan had rightly brought up very early in the dev 
> cycle of this task). I do plan to tackle this in a better way, but 
> given the complexity involved with classloaders (both due to the 
> nature of JUnit 5 and Ant itself) and the fact that I  lost focus on 
> this task for a bit, I haven't been able to come up with a solution. 
> I'll look more into this in the upcoming days and see how we can 
> improve this.
>
> If I misunderstood your use case, please do let us know.
>
> [1] https://ant.apache.org/manual/Tasks/junitlauncher.html
>
> -Jaikiran


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Re: ClassLoaders in JUnit Launcher Task

Posted by Jaikiran Pai <ja...@gmail.com>.
HelloLucas,


On 01/06/18 10:46 PM, Lucas Bullen wrote:
>
> However, when attempting to do this I run into an issue with ClassLoaders.
> JUnitLauncherTask.execute() [2] sets the thread's ClassLoader to its own or
> to an AntClassLoader, both of which do not contain the junit TestEngine's

Which test engine are you using and where are the jars for those 
located? The vintage and the jupiter test engines (part of JUnit 5) or 
any test engine for that matter, can be placed in the ANT_HOME/lib 
directory and they should be picked up. Or you can pass the -lib option 
while launching Ant to pass the location of those jars. These methods 
have been noted in the documentation of the task[1]
>
> Our previous way of getting around this was to create our own ClassLoader
> with the required TestEngines and set this to the current thread's
> ClassLoader to ensure that the TestEngines are found [4].
>
> This technique no longer works for the JUnitLauncherTask as it resets the
> ClassLoader right before executing the tests. Does anyone have a suggestion
> on how to resolve this issue?

The way JUnit 5 works, it uses the thread context classloader to find 
the test engines (and even test cases). That's why the JUnitLauncherTask 
sets it up in a manner that the right classloader is setup before 
executing the tests.

I looked at the customer classloader you pointed to, in your footnotes. 
How was that being setup in the Ant build, previously?

Overall, if I understand your question correctly - you do not want to 
add the *test engines* to the ANT_HOME/lib and neither do you want to 
pass the -lib option while launching Ant and instead want to define a 
classpath in your build file and use that classpath for finding the test 
engines? If that's the case, then yes it's currently a limitation (one 
that which Stefan had rightly brought up very early in the dev cycle of 
this task). I do plan to tackle this in a better way, but given the 
complexity involved with classloaders (both due to the nature of JUnit 5 
and Ant itself) and the fact that I  lost focus on this task for a bit, 
I haven't been able to come up with a solution. I'll look more into this 
in the upcoming days and see how we can improve this.

If I misunderstood your use case, please do let us know.

[1] https://ant.apache.org/manual/Tasks/junitlauncher.html

-Jaikiran

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org