Custom TestNG Annotation and linking it to listeners

4,233 views
Skip to first unread message

parikshit chakraborty

unread,
Mar 24, 2015, 3:20:07 AM3/24/15
to testng...@googlegroups.com
Hi,

I am trying to write Custom Annotation for my project to do some tasks and followed https://github.com/cbeust/testng/issues/469 to come up with the annotation. Below is the custom annotation code snippet

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSet {
public String dataSetLocation() default "";

}


Below is the listener code snippet

@Listeners
public class DataSetListener implements IInvokedMethodListener2, ITestListener{

String xmlData = null;

public void afterInvocation(IInvokedMethod arg0, ITestResult arg1,
ITestContext arg2) {
// TODO Auto-generated method stub
}

public void beforeInvocation(IInvokedMethod method, ITestResult result,
ITestContext context) {
if (method.isTestMethod() && annotationPresent(method, DataSet.class)) {
System.out.println(xmlData);
}
}

        public void onStart(ITestContext context) {
ITestNGMethod[] allTestMethods = context.getAllTestMethods();
for (ITestNGMethod iTestNGMethod : context.getAllTestMethods()) {
xmlData = iTestNGMethod.getConstructorOrMethod().getMethod().getAnnotation(DataSet.class).dataSetLocation();
}
}
}


Now when i execute a @Test method with above annotation, nothing happens. The execution doesn't even go to the above listener. Below is the code snippet of Test method. 

Note: Both Custom Annotation, Listener and Test Class are in different package in the same project

@DataSet(dataSetLocation = "New Location")
@Test
public void testDataSetAnnotation() {
System.out.println("printed location in listener");
}

Can anyone please help me with how to link a custom annotation to its corresponding listener. 

Krishnan Mahadevan

unread,
Mar 24, 2015, 4:01:15 AM3/24/15
to testng...@googlegroups.com
Here's a complete working code.

The one thing that you seemed to have missed was basically wiring your Listener to your test class.

import org.testng.Assert;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ITestResult;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Listeners (ParikshitSample.DataSetListener.class)
public class ParikshitSample {

@Test
@DataSet (dataSetLocation = "src/test/resources/foo.xml")
public void showDemo() {
Assert.assertTrue(true);
}

@Retention (RetentionPolicy.RUNTIME)
@Target ({ ElementType.METHOD })
public @interface DataSet {
String dataSetLocation() default "";
}

public static class DataSetListener implements IInvokedMethodListener {

@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
if (!method.isTestMethod()) {
return;
}
DataSet set = method.getTestMethod().getConstructorOrMethod().getMethod().getAnnotation(DataSet.class);
if (set == null) {
return;
}
System.out.println("Data Set Location : [" + set.dataSetLocation() + "]");
}

@Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {

}
}

}

Here's the output :

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.test.ParikshitSample
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNG652Configurator@7b681460
Data Set Location : [src/test/resources/foo.xml]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.255 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.742 s
[INFO] Finished at: 2015-03-24T13:28:46+05:30
[INFO] Final Memory: 27M/449M
[INFO] ------------------------------------------------------------------------







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 http://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

parikshit chakraborty

unread,
Mar 24, 2015, 6:28:05 AM3/24/15
to testng...@googlegroups.com
Thanks Krishnan, it worked.

One question here, is there a way to decouple test class and listener? I mean the way I was doing where I have kept Listener out in another class. The reason why I tried that way is if I have multiple test classes where I am going use that custom annotation then I would have to write same listener class in every test classes where this annotation is being used.

Regards,
Parikshit

Krishnan Mahadevan

unread,
Mar 24, 2015, 6:38:06 AM3/24/15
to testng...@googlegroups.com
Yes. The listener should reside in its own .java class. I bundled up everything in one single class just for demonstration purposes.
Oh btw, because the listener class is embedded in your Test class doesnt mean you have to duplicate it everywhere. You can still refer to it in your test classes (but yes, it kind of sounds a bit of mixup and so its better to have the listener reside in its own .java file)

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/

parikshit chakraborty

unread,
Apr 1, 2015, 7:40:46 AM4/1/15
to testng...@googlegroups.com
Hi Krishnan,

I have tried keeping listener (for the custom annotation) separate in a .java file and added the same in testng suite with <listeners> tag and it worked fine. However, if I remove that <listener> tag and try to execute, it doesn't work. The listener java class doesn't get called at all.

So is there a way to achieve listener call if the listener is kept in a separate .java file (for the custom annotation and in another package) and without adding the listener in testng suite with <listener> tag.

Please help.

Krishnan Mahadevan

unread,
Apr 2, 2015, 2:26:33 PM4/2/15
to testng...@googlegroups.com

Thanks & Regards
Krishnan Mahadevan

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

parikshit chakraborty

unread,
Apr 7, 2015, 5:58:53 AM4/7/15
to testng...@googlegroups.com
Thanks Krishnan, The blog is really helpful...
Reply all
Reply to author
Forward
0 new messages