From f325d9aa7a9505526a2ec933349aaf227ac23b43 Mon Sep 17 00:00:00 2001 From: Julien Herr Date: Thu, 5 Nov 2015 15:53:08 +0100 Subject: Fix #776 Add IClassListener, a @BeforeClass/@AfterClass alternative --- src/main/java/org/testng/IClassListener.java | 7 +++++ src/main/java/org/testng/ITestRunnerFactory.java | 3 +- src/main/java/org/testng/SuiteRunner.java | 25 ++++++++++------ src/main/java/org/testng/TestNG.java | 13 ++++++++- src/main/java/org/testng/TestRunner.java | 33 ++++++++++++++++------ src/main/java/org/testng/internal/Invoker.java | 9 ++++-- .../java/org/testng/internal/TestMethodWorker.java | 20 +++++++++++-- src/main/java/org/testng/remote/RemoteTestNG.java | 9 +++--- 8 files changed, 91 insertions(+), 28 deletions(-) create mode 100644 src/main/java/org/testng/IClassListener.java (limited to 'src/main') diff --git a/src/main/java/org/testng/IClassListener.java b/src/main/java/org/testng/IClassListener.java new file mode 100644 index 00000000..fb56a783 --- /dev/null +++ b/src/main/java/org/testng/IClassListener.java @@ -0,0 +1,7 @@ +package org.testng; + +public interface IClassListener extends ITestNGListener { + + void onBeforeClass(ITestClass testClass, IMethodInstance mi); + void onAfterClass(ITestClass testClass, IMethodInstance mi); +} diff --git a/src/main/java/org/testng/ITestRunnerFactory.java b/src/main/java/org/testng/ITestRunnerFactory.java index 120af35d..3e83ceaf 100644 --- a/src/main/java/org/testng/ITestRunnerFactory.java +++ b/src/main/java/org/testng/ITestRunnerFactory.java @@ -4,11 +4,12 @@ package org.testng; import org.testng.xml.XmlTest; import java.util.Collection; +import java.util.List; /** * A factory for TestRunners to be used by SuiteRunners. */ public interface ITestRunnerFactory { TestRunner newTestRunner(final ISuite suite, final XmlTest test, - Collection listeners); + Collection listeners, List classListeners); } diff --git a/src/main/java/org/testng/SuiteRunner.java b/src/main/java/org/testng/SuiteRunner.java index c405ee1f..5bb13971 100644 --- a/src/main/java/org/testng/SuiteRunner.java +++ b/src/main/java/org/testng/SuiteRunner.java @@ -53,6 +53,7 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener private Injector m_parentInjector; transient private List m_testListeners = Lists.newArrayList(); + transient private List m_classListeners = Lists.newArrayList(); transient private ITestRunnerFactory m_tmpRunnerFactory; transient private ITestRunnerFactory m_runnerFactory; @@ -99,7 +100,8 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener this(configuration, suite, outputDir, runnerFactory, useDefaultListeners, new ArrayList() /* method interceptor */, null /* invoked method listeners */, - null /* test listeners */); + null /* test listeners */, + null /* class listeners */); } protected SuiteRunner(IConfiguration configuration, @@ -109,9 +111,10 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener boolean useDefaultListeners, List methodInterceptors, List invokedMethodListeners, - List testListeners) + List testListeners, + List classListeners) { - init(configuration, suite, outputDir, runnerFactory, useDefaultListeners, methodInterceptors, invokedMethodListeners, testListeners); + init(configuration, suite, outputDir, runnerFactory, useDefaultListeners, methodInterceptors, invokedMethodListeners, testListeners, classListeners); } private void init(IConfiguration configuration, @@ -121,7 +124,8 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener boolean useDefaultListeners, List methodInterceptors, List invokedMethodListener, - List testListeners) + List testListeners, + List classListeners) { m_configuration = configuration; m_suite = suite; @@ -146,6 +150,9 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener if (null != testListeners) { m_testListeners.addAll(testListeners); } + if (null != classListeners) { + m_classListeners.addAll(classListeners); + } m_runnerFactory = buildRunnerFactory(); // Order the tags based on their order of appearance in testng.xml @@ -158,7 +165,7 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener }); for (XmlTest test : xmlTests) { - TestRunner tr = m_runnerFactory.newTestRunner(this, test, m_invokedMethodListeners.values()); + TestRunner tr = m_runnerFactory.newTestRunner(this, test, m_invokedMethodListeners.values(), m_classListeners); // // Install the method interceptor, if any was passed @@ -540,14 +547,14 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, - Collection listeners) { + Collection listeners, List classListeners) { boolean skip = m_skipFailedInvocationCounts; if (! skip) { skip = test.skipFailedInvocationCounts(); } TestRunner testRunner = new TestRunner(m_configuration, suite, test, suite.getOutputDirectory(), suite.getAnnotationFinder(), skip, - listeners); + listeners, classListeners); if (m_useDefaultListeners) { testRunner.addListener(new TestHTMLReporter()); @@ -583,8 +590,8 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, - Collection listeners) { - TestRunner testRunner= m_target.newTestRunner(suite, test, listeners); + Collection listeners, List classListeners) { + TestRunner testRunner= m_target.newTestRunner(suite, test, listeners, classListeners); testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose())); diff --git a/src/main/java/org/testng/TestNG.java b/src/main/java/org/testng/TestNG.java index 6becc092..45cbab8f 100644 --- a/src/main/java/org/testng/TestNG.java +++ b/src/main/java/org/testng/TestNG.java @@ -135,6 +135,7 @@ public class TestNG { private ITestRunnerFactory m_testRunnerFactory; // These listeners can be overridden from the command line + private List m_classListeners = Lists.newArrayList(); private List m_testListeners = Lists.newArrayList(); private List m_suiteListeners = Lists.newArrayList(); private Set m_reporters = Sets.newHashSet(); @@ -707,6 +708,9 @@ public class TestNG { if (listener instanceof ITestListener) { addListener((ITestListener) listener); } + if (listener instanceof IClassListener) { + addListener((IClassListener) listener); + } if (listener instanceof IReporter) { addListener((IReporter) listener); } @@ -750,6 +754,12 @@ public class TestNG { } } + public void addListener(IClassListener listener) { + if (null != listener) { + m_classListeners.add(listener); + } + } + public void addListener(IReporter listener) { if (null != listener) { m_reporters.add(listener); @@ -1293,7 +1303,8 @@ public class TestNG { m_useDefaultListeners, m_methodInterceptors, m_invokedMethodListeners, - m_testListeners); + m_testListeners, + m_classListeners); for (ISuiteListener isl : m_suiteListeners) { result.addListener(isl); diff --git a/src/main/java/org/testng/TestRunner.java b/src/main/java/org/testng/TestRunner.java index c85aaa21..cce56626 100644 --- a/src/main/java/org/testng/TestRunner.java +++ b/src/main/java/org/testng/TestRunner.java @@ -87,6 +87,7 @@ public class TestRunner transient private boolean m_skipFailedInvocationCounts; transient private Collection m_invokedMethodListeners = Lists.newArrayList(); + transient private List m_classListeners = Lists.newArrayList(); /** * All the test methods we found, associated with their respective classes. @@ -154,18 +155,20 @@ public class TestRunner String outputDirectory, IAnnotationFinder finder, boolean skipFailedInvocationCounts, - Collection invokedMethodListeners) + Collection invokedMethodListeners, + List classListeners) { init(configuration, suite, test, outputDirectory, finder, skipFailedInvocationCounts, - invokedMethodListeners); + invokedMethodListeners, classListeners); } public TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, boolean skipFailedInvocationCounts, - Collection listeners) { + Collection invokedMethodListeners, + List classListeners) { init(configuration, suite, test, suite.getOutputDirectory(), suite.getAnnotationFinder(), - skipFailedInvocationCounts, listeners); + skipFailedInvocationCounts, invokedMethodListeners, classListeners); } private void init(IConfiguration configuration, @@ -174,7 +177,8 @@ public class TestRunner String outputDirectory, IAnnotationFinder annotationFinder, boolean skipFailedInvocationCounts, - Collection invokedMethodListeners) + Collection invokedMethodListeners, + List classListeners) { m_configuration = configuration; m_xmlTest= test; @@ -199,8 +203,9 @@ public class TestRunner m_annotationFinder= annotationFinder; m_invokedMethodListeners = invokedMethodListeners; + m_classListeners = classListeners; m_invoker = new Invoker(m_configuration, this, this, m_suite.getSuiteState(), - m_skipFailedInvocationCounts, invokedMethodListeners); + m_skipFailedInvocationCounts, invokedMethodListeners, classListeners); if (suite.getParallel() != null) { log(3, "Running the tests in '" + test.getName() + "' with parallel mode:" + suite.getParallel()); @@ -344,6 +349,9 @@ public class TestRunner // At this point, the field m_testListeners has already been used in the creation addTestListener((ITestListener) listener); } + if (listener instanceof IClassListener) { + m_classListeners.add((IClassListener) listener); + } if (listener instanceof IConfigurationListener) { addConfigurationListener((IConfigurationListener) listener); } @@ -909,7 +917,8 @@ public class TestRunner m_xmlTest.getAllParameters(), m_groupMethods, m_classMethodMap, - this); + this, + m_classListeners); result.add(tmw); } @@ -947,7 +956,8 @@ public class TestRunner params, m_groupMethods, m_classMethodMap, - this); + this, + m_classListeners); } private IMethodInstance[] findClasses(List methodInstances, Class c) { @@ -1491,12 +1501,19 @@ public class TestRunner if(listener instanceof IConfigurationListener) { addConfigurationListener((IConfigurationListener) listener); } + if(listener instanceof IClassListener) { + addClassListener((IClassListener) listener); + } } public void addTestListener(ITestListener il) { m_testListeners.add(il); } + public void addClassListener(IClassListener cl) { + m_classListeners.add(cl); + } + void addConfigurationListener(IConfigurationListener icl) { m_configurationListeners.add(icl); } diff --git a/src/main/java/org/testng/internal/Invoker.java b/src/main/java/org/testng/internal/Invoker.java index 86c892c2..94073b79 100644 --- a/src/main/java/org/testng/internal/Invoker.java +++ b/src/main/java/org/testng/internal/Invoker.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Set; import org.testng.IClass; +import org.testng.IClassListener; import org.testng.IConfigurable; import org.testng.IConfigurationListener; import org.testng.IConfigurationListener2; @@ -67,6 +68,7 @@ public class Invoker implements IInvoker { private final boolean m_skipFailedInvocationCounts; private final Collection m_invokedMethodListeners; private final boolean m_continueOnFailedConfiguration; + private final List m_classListeners; /** Group failures must be synced as the Invoker is accessed concurrently */ private Map m_beforegroupsFailures = Maps.newHashtable(); @@ -106,7 +108,8 @@ public class Invoker implements IInvoker { ITestResultNotifier notifier, SuiteRunState state, boolean skipFailedInvocationCounts, - Collection invokedMethodListeners) { + Collection invokedMethodListeners, + List classListeners) { m_configuration = configuration; m_testContext= testContext; m_suiteState= state; @@ -115,6 +118,7 @@ public class Invoker implements IInvoker { m_skipFailedInvocationCounts = skipFailedInvocationCounts; m_invokedMethodListeners = invokedMethodListeners; m_continueOnFailedConfiguration = XmlSuite.CONTINUE.equals(testContext.getSuite().getXmlSuite().getConfigFailurePolicy()); + m_classListeners = classListeners; } /** @@ -1320,7 +1324,8 @@ public class Invoker implements IInvoker { mi, suite, parameters, - testContext)); + testContext, + m_classListeners)); } return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, diff --git a/src/main/java/org/testng/internal/TestMethodWorker.java b/src/main/java/org/testng/internal/TestMethodWorker.java index ef72ff11..a2634197 100644 --- a/src/main/java/org/testng/internal/TestMethodWorker.java +++ b/src/main/java/org/testng/internal/TestMethodWorker.java @@ -1,6 +1,7 @@ package org.testng.internal; import org.testng.ClassMethodMap; +import org.testng.IClassListener; import org.testng.IMethodInstance; import org.testng.ITestClass; import org.testng.ITestContext; @@ -40,6 +41,7 @@ public class TestMethodWorker implements IWorker { private final ConfigurationGroupMethods m_groupMethods; private final ClassMethodMap m_classMethodMap; private final ITestContext m_testContext; + private final List m_listeners; public TestMethodWorker(IInvoker invoker, IMethodInstance[] testMethods, @@ -47,7 +49,8 @@ public class TestMethodWorker implements IWorker { Map parameters, ConfigurationGroupMethods groupMethods, ClassMethodMap classMethodMap, - ITestContext testContext) + ITestContext testContext, + List listeners) { m_invoker = invoker; m_methodInstances = testMethods; @@ -56,6 +59,7 @@ public class TestMethodWorker implements IWorker { m_groupMethods = groupMethods; m_classMethodMap = classMethodMap; m_testContext = testContext; + m_listeners = listeners; } /** @@ -140,6 +144,10 @@ public class TestMethodWorker implements IWorker { * @param mi */ protected void invokeBeforeClassMethods(ITestClass testClass, IMethodInstance mi) { + for (IClassListener listener : m_listeners) { + listener.onBeforeClass(testClass, mi); + } + // if no BeforeClass than return immediately // used for parallel case when BeforeClass were already invoked if( (null == m_classMethodMap) || (null == m_classMethodMap.getInvokedBeforeClassMethods())) { @@ -184,6 +192,10 @@ public class TestMethodWorker implements IWorker { * @param mi */ protected void invokeAfterClassMethods(ITestClass testClass, IMethodInstance mi) { + for (IClassListener listener : m_listeners) { + listener.onAfterClass(testClass, mi); + } + // if no BeforeClass than return immediately // used for parallel case when BeforeClass were already invoked if( (null == m_classMethodMap) || (null == m_classMethodMap.getInvokedAfterClassMethods()) ) { @@ -283,7 +295,8 @@ class SingleTestMethodWorker extends TestMethodWorker { MethodInstance testMethod, XmlSuite suite, Map parameters, - ITestContext testContext) + ITestContext testContext, + List listeners) { super(invoker, new MethodInstance[] {testMethod}, @@ -291,6 +304,7 @@ class SingleTestMethodWorker extends TestMethodWorker { parameters, EMPTY_GROUP_METHODS, null, - testContext); + testContext, + listeners); } } diff --git a/src/main/java/org/testng/remote/RemoteTestNG.java b/src/main/java/org/testng/remote/RemoteTestNG.java index ec6efd74..1e1ebead 100644 --- a/src/main/java/org/testng/remote/RemoteTestNG.java +++ b/src/main/java/org/testng/remote/RemoteTestNG.java @@ -6,6 +6,7 @@ import com.beust.jcommander.JCommander; import com.beust.jcommander.ParameterException; import org.testng.CommandLineArgs; +import org.testng.IClassListener; import org.testng.IInvokedMethodListener; import org.testng.ISuite; import org.testng.ISuiteListener; @@ -138,11 +139,11 @@ public class RemoteTestNG extends TestNG { m_customTestRunnerFactory= new ITestRunnerFactory() { @Override public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, - Collection listeners) { + Collection listeners, List classListeners) { TestRunner runner = new TestRunner(getConfiguration(), suite, xmlTest, false /*skipFailedInvocationCounts */, - listeners); + listeners, classListeners); if (m_useDefaultListeners) { runner.addListener(new TestHTMLReporter()); runner.addListener(new JUnitXMLReporter()); @@ -268,8 +269,8 @@ public class RemoteTestNG extends TestNG { @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, - Collection listeners) { - TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners); + Collection listeners, List classListeners) { + TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); return tr; } -- cgit v1.2.3