From e9a6c4f4dcdd5a9237f7ec133762fd22c6024135 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Wed, 16 Mar 2022 12:14:48 +0200 Subject: [PATCH] #2734 keep the initial order of listeners (#2737) * #2734 keep the initial order of listeners We need to run listeners at the same order in which they were declared in @Listeners({First.class, Second.class, Third.class}) --- CHANGES.txt | 1 + .../src/main/java/org/testng/TestRunner.java | 2 +- .../test/java/org/testng/TestRunnerTest.java | 94 +++++++++++++++++++ testng-core/src/test/resources/testng.xml | 6 ++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 testng-core/src/test/java/org/testng/TestRunnerTest.java diff --git a/CHANGES.txt b/CHANGES.txt index 4556cc3a23..46be0f07ba 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,7 @@ Fixed: assertEqualsNoOrder for Collection and Iterators size check was missing ( Fixed: GITHUB-2709: Testnames not working together with suites in suite (Martin Aldrin) Fixed: GITHUB-2704: IHookable and IConfigurable callback discrepancy (Krishnan Mahadevan) Fixed: GITHUB-2637: Upgrade to JDK11 as the minimum JDK requirements (Krishnan Mahadevan) +Fixed: GITHUB-2734: Keep the initial order of listeners (Andrei Solntsev) 7.5 Fixed: GITHUB-2701: Bump gradle version to 7.3.3 to support java17 build (ZhangJian He) diff --git a/testng-core/src/main/java/org/testng/TestRunner.java b/testng-core/src/main/java/org/testng/TestRunner.java index bfcab4b23a..05f3e9ac3b 100644 --- a/testng-core/src/main/java/org/testng/TestRunner.java +++ b/testng-core/src/main/java/org/testng/TestRunner.java @@ -345,7 +345,7 @@ private void initListeners() { // Find all the listener factories and collect all the listeners requested in a // @Listeners annotation. // - Set> listenerClasses = Sets.newHashSet(); + Set> listenerClasses = Sets.newLinkedHashSet(); Class listenerFactoryClass = null; for (IClass cls : getTestClasses()) { diff --git a/testng-core/src/test/java/org/testng/TestRunnerTest.java b/testng-core/src/test/java/org/testng/TestRunnerTest.java new file mode 100644 index 0000000000..e5afcfad51 --- /dev/null +++ b/testng-core/src/test/java/org/testng/TestRunnerTest.java @@ -0,0 +1,94 @@ +package org.testng; + +import static java.util.Collections.emptyList; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.stream.Collectors; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; +import org.testng.internal.Configuration; +import org.testng.internal.IConfiguration; +import org.testng.internal.objects.DefaultTestObjectFactory; +import org.testng.xml.XmlClass; +import org.testng.xml.XmlSuite; +import org.testng.xml.XmlTest; + +public class TestRunnerTest { + @Test + public void listenersShouldBeAppliedInDeclarationOrder_one() { + TestRunner testRunner = createTestRunner(TestWithOneListener.class); + + List configurationListeners = testRunner.getConfigurationListeners(); + + assertThat(classesOf(configurationListeners, 1)).containsExactly(FooListener.class); + } + + @Test + public void listenersShouldBeAppliedInDeclarationOrder_two() { + TestRunner testRunner = createTestRunner(TestWithTwoListeners.class); + + List configurationListeners = testRunner.getConfigurationListeners(); + + assertThat(classesOf(configurationListeners, 2)) + .containsExactly(FooListener.class, BarListener.class); + } + + @Test + public void listenersShouldBeAppliedInDeclarationOrder_three() { + TestRunner testRunner = createTestRunner(TestWithThreeListeners.class); + + List configurationListeners = testRunner.getConfigurationListeners(); + + assertThat(classesOf(configurationListeners, 3)) + .containsExactly(FooListener.class, BarListener.class, ZooListener.class); + } + + @Listeners(FooListener.class) + public static class TestWithOneListener { + @Test + public void some() {} + } + + @Listeners({FooListener.class, BarListener.class}) + public static class TestWithTwoListeners { + @BeforeMethod + public void setup() {} + + @Test + public void some() {} + } + + @Listeners({FooListener.class, BarListener.class, ZooListener.class}) + public static class TestWithThreeListeners { + @Test + public void some() {} + } + + public static class FooListener implements IConfigurationListener {} + + public static class BarListener implements IConfigurationListener {} + + public static class ZooListener implements IConfigurationListener {} + + private List> classesOf(List values, int limit) { + return values.stream().limit(limit).map(Object::getClass).collect(Collectors.toList()); + } + + private TestRunner createTestRunner(Class testClass) { + IConfiguration configuration = new Configuration(); + configuration.setObjectFactory(new DefaultTestObjectFactory()); + XmlSuite xmlSuite = new XmlSuite(); + XmlTest xmlTest = new XmlTest(xmlSuite); + xmlSuite.addTest(xmlTest); + XmlClass xmlClass = new XmlClass(testClass.getName()); + xmlTest.getXmlClasses().add(xmlClass); + String outputDir = "build/reports/tests/test"; + ITestRunnerFactory factory = + (suite, test, listeners, classListeners) -> + new TestRunner(configuration, suite, test, false, listeners, classListeners); + ISuite suite = new SuiteRunner(configuration, xmlSuite, outputDir, factory, (o1, o2) -> 0); + return factory.newTestRunner(suite, xmlTest, emptyList(), emptyList()); + } +} diff --git a/testng-core/src/test/resources/testng.xml b/testng-core/src/test/resources/testng.xml index 1fb2c3dc0d..1a7644b710 100644 --- a/testng-core/src/test/resources/testng.xml +++ b/testng-core/src/test/resources/testng.xml @@ -927,6 +927,12 @@ + + + + + +