New TestNG feature: support for ServiceLoader

1,787 views
Skip to first unread message

Cédric Beust ♔

unread,
Jun 17, 2011, 3:37:43 PM6/17/11
to testng...@googlegroups.com
Hi everyone,

I just added support for ServiceLoader to TestNG.

If you're not familiar with the tremendously useful class ServiceLoader, it's a very simple facility to look up implementations of interfaces found on the classpath. This comes in particularly handy for TestNG when you want to define listeners and you don't want to bother specifying them in testng.xml/ant/maven/whatever.

With ServiceLoader, all you need to do is create a jar file that contains your listener(s) and a few configuration files, put that jar file on the classpath when you run TestNG and TestNG will automatically find them.

Here is a concrete example of how it works.

Let's start by creating a listener (any TestNG listener should work):

package test.tmp;


public class TmpSuiteListener implements ISuiteListener {

  public static boolean start = false;

  public static boolean finish = false;


  @Override

  public void onFinish(ISuite suite) {

    System.out.println("Finishing");

  }


  @Override

  public void onStart(ISuite suite) {

    System.out.println("Starting");

  }


}


Compile it, and then create a file at the location META-INF/services/org.testng.ITestNGListener, which will name the implementation(s) you want for this interface.

You should end up with the following directory structure, with only two files:

$ tree
|____META-INF
| |____services
| | |____org.testng.ITestNGListener
|____test
| |____tmp
| | |____TmpSuiteListener.class

$ cat META-INF/services/org.testng.ITestNGListener
test.tmp.TmpSuiteListener

Create a jar of this directory:

$ jar cvf ../sl.jar .
added manifest
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/org.testng.ITestNGListener(in = 26) (out= 28)(deflated -7%)
adding: test/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/TmpSuiteListener.class(in = 849) (out= 470)(deflated 44%)

Next, put this jar file on your classpath when you invoke TestNG:

$ java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml
Starting
f2 11 2
PASSED: f2("2")
Finishing

This mechanism allows you to apply the same set of listeners to an entire organization just be adding a jar file to the classpath, instead of asking every single developer to remember to specify these listeners in their testng.xml file.

Please try this feature on the beta (http://testng.org/beta ) and let me know how it works for you.

Caveat: this feature is only available on Java 6. You won't be able to use it on older versions of Java, but TestNG should still keep working for you. Let me know if you're using Java 5 and you're having problems with this new jar file.

-- 
Cédric


Srikanth K

unread,
Feb 24, 2016, 2:13:02 AM2/24/16
to testng-users, ced...@beust.com
Hi,
I have followed all the steps mentioned here in order to implement service loaders and i am trying to execute the test cases in eclipse. i have followed these steps. 1. Disable the default listners. 2. added the jar created for service loader in build path. 3. using testng.xml file > run as testNG. But the test cases are running sequentially :(. I am clueless where i might be wrong. Please help me with possible suggestions. I need to deliver this solution urgently.

Thanks in advance...
regards,
Srikanth

Krishnan Mahadevan

unread,
Feb 24, 2016, 2:15:55 AM2/24/16
to testng...@googlegroups.com
What exactly are you trying to do ? How does adding listeners to your project affect test execution [ sequential/parallel] ?

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users...@googlegroups.com.
To post to this group, send email to testng...@googlegroups.com.
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

Srikanth K

unread,
Feb 24, 2016, 10:41:29 PM2/24/16
to testng-users, ced...@beust.com
Hi Krishnan,

i am trying to implement 'iAltersuitListner' to enable parallel execution.We spent two days trying to figure out & have followed all the steps mentioned by Cedric but can't get the serviceloader to work. Would you please list down the steps again in a more simplified manner or possibly a youtube video would be of great option. 

The procedure we followed -
1. Created a wrapper class to implement IAlterSuiteListener .
package org.com.mycompany.CORE;

public class TestNGWrapper implements IAlterSuiteListener  {
   
     public static final String ALTER_SUITE_LISTENER = "AlterSuiteListener";{
}
    @Override
    public void alter(List<XmlSuite> suites) {
        XmlSuite suite = suites.get(0);
        suite.setName(getClass().getSimpleName());
          suite.setParallel(ParallelMode.METHODS) ;
        suite.setThreadCount(3);
    }
}
 Next, followed the steps mentioned by Cedric for creating the serviceloader jar file & added it in the build path of the project.
Please suggest where we might be going wrong.

Thanks a lot for your reply,
Srikanth.

Srikanth K

unread,
Feb 24, 2016, 11:42:34 PM2/24/16
to testng-users, ced...@beust.com
 I get the Error: 'Could not find or load main class org.testng.TestNG' when i run through the command using cmd - >java -classpath serviceLoader.jar;testng.jar;bin
 org.testng.TestNG %1%
and when i run in eclipse, listeners are not invoked. 

Krishnan Mahadevan

unread,
Feb 25, 2016, 2:10:19 AM2/25/16
to testng...@googlegroups.com
Srikanth,

Lets take a step back here. 

Can you please help answer the following questions ?

* What build tool does your project use ? [ Gradle/Ant/Maven ] ? If nothing is being used, I would suggest that you please consider moving over to using Maven or Gradle for that matter. Its a lot more easier to run tests via a build tool.
* How are you currently setting up your classpath ? Please feel free to elaborate this as much as possible [ even if it means you have to write up a step by step procedure, so be it but please do so ]

With respect to your problem, its still very much isolated to CLASSPATH being messed up.

When you use java -cp on windows make sure that your jars are separated via semi colons and on NON Windows its a colon.

Lastly, TestNG relies on ServiceLoaders that the JDK exposes. So there is no need for you to create any jar out of it.

Within your project make sure that there is a folder named META-INF/services/ either in src/main/resources (or) src/test/resources wherein you create a file named org.testng.ITestNGListener within which you call out the fully qualified class names of your listeners and that should suffice.


Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

On Thu, Feb 25, 2016 at 10:12 AM, Srikanth K <srikan...@gmail.com> wrote:
 I get the Error: 'Could not find or load main class org.testng.TestNG' when i run through the command using cmd - >java -classpath serviceLoader.jar;testng.jar;bin
 org.testng.TestNG %1%
and when i run in eclipse, listeners are not invoked. 

--

Srikanth K

unread,
Feb 25, 2016, 6:08:27 AM2/25/16
to testng-users, ced...@beust.com
Hi Krishnan,
1. We use maven to build projects. 
2. Normally, i set up the class path as follows-
    > right click on the project>go to properties> click on libraries tab > click on 'add external JARs' tab (if we have to add external jars such as service loader.jar)
    > click on 'add library' tab > select the required libraries & click on ok. Below is screenshot of projects classpath.



I also found another link from where i downloaded a demo project from the below link for service loaders and it works fine but when i try to create a similar project with the same settings, it doesn't run. :( And whem i run the demo project & the project i created using CMD, my project gives error as 'could not find or load main class org.testng.TestNG'.

url - http://examples.javacodegeeks.com/enterprise-java/testng/testng-listeners-example/#adding_listeners_serviceloader
Below is the project structure -

We are very particular about the implementation of the service loader jar file so please suggest steps where in i could include the service loader jar file.

Thanks much

Auto Generated Inline Image 1
Auto Generated Inline Image 2

Krishnan Mahadevan

unread,
Feb 25, 2016, 6:22:20 AM2/25/16
to testng...@googlegroups.com
I am re-iterating what I mentioned earlier. You are doing a lot of things incorrectly.
In a Maven project you should never be adding anything to the build path using the approach you are doing. A Maven project is expected to get its CLASSPATH updated ONLY via the pom.xml by means of <dependencies>

Your screenshot also suggests that you have not added TestNG as a dependency in your pom file, but you seem to have added it as a reference library. That is wrong.

Please ensure that you add TestNG as a maven dependency [ Refer to this link which explicitly tells you how to do this : http://testng.org/doc/maven.html ] Make sure you add the latest version of TestNG

For you to be able to leverage your listener via service loaders, do the following

Assumption : Your TestNG listener resides in src/main/java

1. Create a file named org.testng.ITestNGListener [ You have created it incorrectly. Your file name reads org.testng.ITestNGListener.txt. It should not have any extensions ] under src/main/resources/META-INF/services. If your Listener resides under src/test/java then make sure you create the org.testng.ITestNGListener under src/test/resources/META-INF/services folder. Please ensure you create the folder structure if its not available.
2. Add your listener's fully qualified package name into the file org.testng.ITestNGListener

From the command prompt [ Maven needs to be installed ] run the command mvn clean test [ This leverages the maven surefire-plugin to run your @Test annotated TestNG methods and also automatically loads your listeners via ServiceLoaders ]

If you follow these instructions to the word, you should be able to get this to work immediately.


PS : I am re-iterating, please DO NOT add libraries as referenced libraries via the eclipse IDE. They will work ONLY when you execute your tests from within eclipse. They will not run when you run from the command prompt.
There should be no reason for you to resort to running your tests via java -cp. You should be running your tests only by using mvn clean test. If you have to use java -cp then you will need to revisit a lot of things [ That's a topic for another day :) ]


Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

Srikanth K

unread,
Feb 25, 2016, 7:28:03 AM2/25/16
to testng-users, ced...@beust.com
Hi Krishnan,
I was able to run the service loader successfully. Thanks a millions !!! :)

The available references do not mention about creating the org.testng.ITestNGListener under src/test/resources/META-INF/services folder. And one more thing i found out was that the file with the name org.testng.ITestNGListener has to be saved as 'all files'. It was such a learning experience.

Thanks a lot

Krishnan mahadevan

unread,
Feb 25, 2016, 10:05:51 AM2/25/16
to testng...@googlegroups.com
Srikanth

The reason perhaps why that's not explicitly mentioned is because :

1. The presence of the file in src/main/resources or src/test/resources depends upon where your class resides. So it boils down to Java knowledge.
2. The part about extensions of the file name was perhaps not called out because its a concept of ServiceLoaders in Java. So maybe the assumption was that a person who first learn what service loaders do before using it in TestNG.

-Krishnan Mahadevan


"All the desirable things in life are either illegal, expensive, fattening or in love with someone else"

From: Srikanth K
Sent: ‎25-‎02-‎2016 17:58
To: testng-users
Cc: ced...@beust.com
Subject: [testng-users] Re: New TestNG feature: support for ServiceLoader

Srikanth K

unread,
Feb 26, 2016, 2:20:28 AM2/26/16
to testng-users, ced...@beust.com
Hello Krishnan,
I am trying to implement two different listeners 1. TestListenerAdapter and 2. IAlterSuiteListener into a single projects service loader.
>To do this, i added both the listener's fully qualified package names into the file org.testng.ITestNGListener.
>Next, i created service loader jar file of both the class files of these two listeners & added it to the class path.
I am not able to invoke the service loader. Not sure if it is possible to include more than one listener into service loader. OR what would be the correct approach to achieve service loaders for more than one listeners?

Thanks much,
Srikanth


Krishnan Mahadevan

unread,
Feb 26, 2016, 2:53:14 AM2/26/16
to testng...@googlegroups.com
A ServiceLoader can contain any number of entries in it. So that shouldn't be a problem.


Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/
Message has been deleted

Srikanth K

unread,
Mar 11, 2016, 6:58:59 AM3/11/16
to testng-users
Hi Krishnan,
 
Is it mandatory to add the META-INF folder and the listener class under source folder?  I was able to implement service loaders successfully following your instructions but now a new problem has arisen. Our framework does not allow any source folders as we have a maven module in place.I have tried by adding the service loader jar and the listener class under the normal folder structure(not src/main or src/test). Need your help to come to a conclusion as i have spent enough time over it.

Thanks much,
Srikanth 

Krishnan mahadevan

unread,
Mar 11, 2016, 9:38:19 PM3/11/16
to testng...@googlegroups.com
That's a requirement from JDK if you are to use service loader capabilities that it exposes. TestNG is just piggy backing on that JDK capability to let you automatically load service loaders. So not sure what else can be done here.

-Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else"

From: Srikanth K
Sent: ‎11-‎03-‎2016 17:29
To: testng-users
Subject: Re: [testng-users] Re: New TestNG feature: support for ServiceLoader

--
Reply all
Reply to author
Forward
0 new messages