Implementing multiple listener interfaces

1,149 views
Skip to first unread message

ddimitrov

unread,
May 7, 2013, 3:40:42 AM5/7/13
to testn...@googlegroups.com
I have a class that implements both IInvokedMethodListener and IReporter - the use case is that I record some information while the test runs and I output it at the end.

What I found is that my listener gets called multiple times per test method invocation. The reason I have found so far is that the TestRunner#initListeners method calls SuiteRunner#addListener multiple times if it happens to implement two or more of ISuiteListener, IInvokedMethodListener, IReporter. This in turn causes the listener to be added as many times to each collection. 

A fix I would suggest is to either change SuiteRunner#addListener to check that the listener has not been already added to the collection.

Cédric Beust ♔

unread,
May 7, 2013, 4:35:01 PM5/7/13
to testn...@googlegroups.com
But that would break the behavior. These interfaces implement different methods, if you're adding a listener implementing two interfaces, surely you expect all the methods that you implement to be called, right?

For example, with your logic, you would add a reporter listener but its methods would never be invoked...

-- 
Cédric


-- 
Cédric



--
You received this message because you are subscribed to the Google Groups "testng-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-dev+...@googlegroups.com.
To post to this group, send email to testn...@googlegroups.com.
Visit this group at http://groups.google.com/group/testng-dev?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

ddimitrov

unread,
May 19, 2013, 9:08:42 PM5/19/13
to testn...@googlegroups.com, ced...@beust.com
Cedric, I think I am not conveying what I mean - I guess it would be better explained by example:

public class TestCounter implements IReporter, IInvokedMethodListener  {
    int count;
    public void beforeInvocation(IInvokedMethod m, ITestResult r) { 
       count++; 
    }
    public void afterInvocation(IInvokedMethod method, ITestResult testResult) { }
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { 
        System.out.println(count);
    }
}

@Listeners(TestCounter)
public class TestWithOneMethod {
    @Test public void test() { assert System.nanoTime() > 0; }
}

As there is only one test method, I would expect that the counter would print "1" - with the current implementation it would print "2". If that is on purpose, it is worth mentioning it in the docs, as I and my colleagues find it counterintuitive. If not, I would be glad to work with you on fixing it.

Cédric Beust ♔

unread,
May 20, 2013, 2:16:02 AM5/20/13
to testn...@googlegroups.com
Hi Dimitar,

This behavior is necessary and intentional. You are suggesting that if I'm trying to add a listener, any listener, I should double check if that instance hasn't been added already, and if it has, not add it.

Such implementation would make it impossible to define a listener that implements two interfaces since only one of the listeners would be added (either IReporter or IInvokedMethodListener).

-- 
Cédric


-- 
Cédric



ddimitrov

unread,
May 20, 2013, 3:26:14 AM5/20/13
to testn...@googlegroups.com, ced...@beust.com
Hi Cedric, I can see why the current implementation behaves the way it does, but that doesn't help me rationalize why does TestNG call the 'beforeInvoke' different number of times depending on whether we implement the counting ant the printing part in the same class or in different classes.

I am suggesting that the behavior should be changed, so that the "beforeInvoke" method of each listener would be called once and only once before a test method is invoked, and the "generateReport" method would be invoked once and only once when all tests have run and all other listeners invoked. 

This behavior should be consistent, regardless of which parts of the test lifecycle a listener listens to (i.e. a listener class should be able to implement all interfaces and not receive duplicate notifications).


Cédric Beust ♔

unread,
May 20, 2013, 11:51:19 AM5/20/13
to testn...@googlegroups.com
Ok I'll take a closer look.


-- 
Cédric



Cédric Beust ♔

unread,
May 25, 2013, 1:18:02 PM5/25/13
to testn...@googlegroups.com
Hi Dimitar,

You are right, there was a bug in how I handle these listeners. I just uploaded a fix, can you try it? It's at http://testng.org/beta

Thanks for your patience!

-- 
Cédric


-- 
Cédric



On Mon, May 20, 2013 at 12:26 AM, ddimitrov <dimitar....@gmail.com> wrote:

ddimitrov

unread,
Jun 10, 2013, 4:36:43 AM6/10/13
to testn...@googlegroups.com, ced...@beust.com
Hi Cedric, I can confirm that the Beta build foxes my issue.

While testing, I found another peculiarity (I am mentioning it just in case it matters) - the double invocation was happening when multi-interface listener was registed using @Listeners annotation, but not when I specified it in the "Listeners" tab of the IntelliJ test runner...

Thank you!
Dimitar

ddimitrov

unread,
Aug 14, 2013, 6:40:12 PM8/14/13
to testn...@googlegroups.com, ced...@beust.com
Is there any plan to release the patch I tested? 
I don't see it mentioned in the Github release notes for the next release.

Dimitar

Cédric Beust ♔

unread,
Aug 15, 2013, 12:11:07 AM8/15/13
to testn...@googlegroups.com
Since it was in the beta build I sent you, the patch is in, even if I forgot to add it to the release notes :)


-- 
Cédric



--
You received this message because you are subscribed to the Google Groups "testng-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-dev+...@googlegroups.com.
To post to this group, send email to testn...@googlegroups.com.

jitendra kandula

unread,
Dec 5, 2013, 4:18:22 AM12/5/13
to testn...@googlegroups.com, ced...@beust.com
Hi Cedric,

Is this part of latest release (6.8.5)? Would it solve the below problem?

I am currently using 6.8.5 and I have registered an ISuiteListener using annotation. In suite.xml have two set of test groups. In this scenario Suite listener is getting registered with two different instances per TestRunner and finally getting triggered twice. 

Thanks for you time.
Jitendra
Reply all
Reply to author
Forward
0 new messages