Skip to content

Commit a781326

Browse files
committed
Allow listeners to be disabled at runtime
Closes #2381
1 parent 23bb95f commit a781326

File tree

10 files changed

+324
-1
lines changed

10 files changed

+324
-1
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Current (7.10.0)
2+
Fixed: GITHUB-2381: Controlling the inclusion of the listener at runtime (Krishnan Mahadevan)
23
Fixed: GITHUB-3082: IInvokedMethodListener Iinvoked method does not return correct instance during @BeforeMethod, @AfterMethod and @AfterClass (Krishnan Mahadevan)
34
Fixed: GITHUB-3084: Document project's PGP artifact signing keys (Krishnan Mahadevan)
45
Fixed: GITHUB-3079: Associate a unique id with every test class object instantiated by TestNG (Krishnan Mahadevan)

testng-core-api/src/main/java/org/testng/ITestNGListener.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,10 @@
55
*
66
* @author cbeust
77
*/
8-
public interface ITestNGListener {}
8+
public interface ITestNGListener {
9+
10+
/** @return - <code>true</code> if the current listener can be considered for execution. */
11+
default boolean isEnabled() {
12+
return true;
13+
}
14+
}

testng-core/src/main/java/org/testng/TestNG.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,9 @@ public void addListener(ITestNGListener listener) {
731731
if (listener == null) {
732732
return;
733733
}
734+
if (!listener.isEnabled()) {
735+
return;
736+
}
734737
if (listener instanceof IExecutionVisualiser) {
735738
IExecutionVisualiser visualiser = (IExecutionVisualiser) listener;
736739
maybeAddListener(m_executionVisualisers, visualiser);

testng-core/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ private void transform(
159159
Constructor<?> testConstructor,
160160
Method testMethod,
161161
Class<?> whichClass) {
162+
if (!m_transformer.isEnabled()) {
163+
return;
164+
}
162165
//
163166
// Transform @Test
164167
//

testng-core/src/test/java/test/listeners/ListenersTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import org.testng.internal.ExitCode;
2020
import org.testng.xml.XmlSuite;
2121
import test.SimpleBaseTest;
22+
import test.listeners.issue2381.FactoryTestClassSample;
23+
import test.listeners.issue2381.SampleGlobalListener;
24+
import test.listeners.issue2381.SampleTransformer;
2225
import test.listeners.issue2638.DummyInvokedMethodListener;
2326
import test.listeners.issue2638.TestClassASample;
2427
import test.listeners.issue2638.TestClassBSample;
@@ -524,6 +527,49 @@ public void testSkipStatusInBeforeAndAfterConfigurationMethod(
524527
assertThat(listener.getLogs()).containsExactlyElementsOf(expected);
525528
}
526529

530+
@Test(description = "GITHUB-2381")
531+
public void ensureListenersCanBeDisabled() {
532+
SampleGlobalListener.clearLogs();
533+
SampleTransformer.clearLogs();
534+
TestNG testng =
535+
create(test.listeners.issue2381.TestClassSample.class, FactoryTestClassSample.class);
536+
SampleGlobalListener listener = new SampleGlobalListener();
537+
SampleTransformer transformer = new SampleTransformer();
538+
testng.addListener(listener);
539+
testng.addListener(transformer);
540+
testng.run();
541+
assertThat(SampleGlobalListener.getLogs()).isEmpty();
542+
assertThat(SampleTransformer.getLogs()).isEmpty();
543+
}
544+
545+
@Test(description = "GITHUB-2381")
546+
public void ensureListenersCanBeDisabledViaCLI() {
547+
SampleGlobalListener.clearLogs();
548+
SampleTransformer.clearLogs();
549+
String listeners =
550+
String.join(",", SampleGlobalListener.class.getName(), SampleTransformer.class.getName());
551+
String testClasses =
552+
String.join(
553+
",",
554+
test.listeners.issue2381.TestClassSample.class.getName(),
555+
FactoryTestClassSample.class.getName());
556+
List<String> args = List.of("-listener", listeners, "-testclass", testClasses);
557+
TestNG.privateMain(args.toArray(String[]::new), null);
558+
assertThat(SampleGlobalListener.getLogs()).isEmpty();
559+
assertThat(SampleTransformer.getLogs()).isEmpty();
560+
}
561+
562+
@Test(description = "GITHUB-2381")
563+
public void ensureListenersCanBeDisabledViaSuiteFile() {
564+
SampleGlobalListener.clearLogs();
565+
SampleTransformer.clearLogs();
566+
TestNG testng = new TestNG();
567+
testng.setTestSuites(List.of("src/test/resources/2381.xml"));
568+
testng.run();
569+
assertThat(SampleGlobalListener.getLogs()).isEmpty();
570+
assertThat(SampleTransformer.getLogs()).isEmpty();
571+
}
572+
527573
@Test(description = "GITHUB-3082")
528574
public void ensureListenerWorksWithCorrectTestClassInstance() {
529575
TestNG tng = create(test.listeners.issue3082.TestClassSample.class);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package test.listeners.issue2381;
2+
3+
import org.testng.annotations.AfterSuite;
4+
import org.testng.annotations.BeforeSuite;
5+
import org.testng.annotations.DataProvider;
6+
import org.testng.annotations.Factory;
7+
import org.testng.annotations.Test;
8+
9+
public class FactoryTestClassSample {
10+
11+
@Factory(dataProvider = "dp")
12+
public FactoryTestClassSample(int ignored) {}
13+
14+
@DataProvider
15+
public static Object[][] dp() {
16+
return new Object[][] {{1}};
17+
}
18+
19+
@BeforeSuite
20+
public void beforeSuite() {}
21+
22+
@Test
23+
public void testMethod() {}
24+
25+
@AfterSuite
26+
public void afterSuite() {}
27+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package test.listeners.issue2381;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import org.testng.IAlterSuiteListener;
7+
import org.testng.IClassListener;
8+
import org.testng.IExecutionListener;
9+
import org.testng.IExecutionVisualiser;
10+
import org.testng.IInvokedMethod;
11+
import org.testng.IInvokedMethodListener;
12+
import org.testng.IReporter;
13+
import org.testng.ISuite;
14+
import org.testng.ISuiteListener;
15+
import org.testng.ITestClass;
16+
import org.testng.ITestContext;
17+
import org.testng.ITestListener;
18+
import org.testng.ITestResult;
19+
import org.testng.xml.XmlSuite;
20+
21+
public class SampleGlobalListener
22+
implements IExecutionListener,
23+
IAlterSuiteListener,
24+
ISuiteListener,
25+
ITestListener,
26+
IInvokedMethodListener,
27+
IClassListener,
28+
IExecutionVisualiser,
29+
IReporter {
30+
31+
private static final List<String> logs = new ArrayList<>();
32+
33+
public static List<String> getLogs() {
34+
return Collections.unmodifiableList(logs);
35+
}
36+
37+
public static void clearLogs() {
38+
logs.clear();
39+
}
40+
41+
@Override
42+
public void onExecutionStart() {
43+
logs.add("onExecutionStart");
44+
}
45+
46+
@Override
47+
public void alter(List<XmlSuite> suites) {
48+
logs.add("alter");
49+
}
50+
51+
@Override
52+
public void onStart(ISuite suite) {
53+
logs.add("onStart(ISuite)");
54+
}
55+
56+
@Override
57+
public void onStart(ITestContext context) {
58+
logs.add("onStart(ITestContext)");
59+
}
60+
61+
@Override
62+
public void onBeforeClass(ITestClass testClass) {
63+
logs.add("onBeforeClass");
64+
}
65+
66+
@Override
67+
public void consumeDotDefinition(String dotDefinition) {
68+
logs.add("consumeDotDefinition");
69+
}
70+
71+
@Override
72+
public void onTestStart(ITestResult result) {
73+
logs.add("onTestStart(ITestResult)");
74+
}
75+
76+
@Override
77+
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
78+
logs.add("beforeInvocation");
79+
}
80+
81+
@Override
82+
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
83+
logs.add("afterInvocation");
84+
}
85+
86+
@Override
87+
public void onTestSuccess(ITestResult result) {
88+
logs.add("onTestSuccess(ITestResult)");
89+
}
90+
91+
@Override
92+
public void onTestFailure(ITestResult result) {
93+
logs.add("onTestFailure(ITestResult)");
94+
}
95+
96+
@Override
97+
public void onTestSkipped(ITestResult result) {
98+
logs.add("onTestSkipped(ITestResult)");
99+
}
100+
101+
@Override
102+
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
103+
logs.add("onTestFailedButWithinSuccessPercentage(ITestResult)");
104+
}
105+
106+
@Override
107+
public void onTestFailedWithTimeout(ITestResult result) {
108+
logs.add("onTestFailedWithTimeout(ITestResult)");
109+
}
110+
111+
@Override
112+
public void onAfterClass(ITestClass testClass) {
113+
logs.add("onAfterClass");
114+
}
115+
116+
@Override
117+
public void onFinish(ITestContext context) {
118+
logs.add("onFinish(ITestContext)");
119+
}
120+
121+
@Override
122+
public void onFinish(ISuite suite) {
123+
logs.add("onFinish(ISuite)");
124+
}
125+
126+
@Override
127+
public void generateReport(
128+
List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
129+
logs.add("generateReport");
130+
}
131+
132+
@Override
133+
public void onExecutionFinish() {
134+
logs.add("onExecutionFinish");
135+
}
136+
137+
@Override
138+
public boolean isEnabled() {
139+
return false;
140+
}
141+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package test.listeners.issue2381;
2+
3+
import java.lang.reflect.Constructor;
4+
import java.lang.reflect.Method;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.List;
8+
import org.testng.IAnnotationTransformer;
9+
import org.testng.annotations.IConfigurationAnnotation;
10+
import org.testng.annotations.IDataProviderAnnotation;
11+
import org.testng.annotations.IFactoryAnnotation;
12+
import org.testng.annotations.IListenersAnnotation;
13+
import org.testng.annotations.ITestAnnotation;
14+
15+
public class SampleTransformer implements IAnnotationTransformer {
16+
17+
private static final List<String> logs = new ArrayList<>();
18+
19+
public static List<String> getLogs() {
20+
return Collections.unmodifiableList(logs);
21+
}
22+
23+
public static void clearLogs() {
24+
logs.clear();
25+
}
26+
27+
@Override
28+
public boolean isEnabled() {
29+
return false;
30+
}
31+
32+
@Override
33+
public void transform(IListenersAnnotation annotation, Class<?> testClass) {
34+
logs.add("transform_listener");
35+
}
36+
37+
@Override
38+
public void transform(IDataProviderAnnotation annotation, Method method) {
39+
logs.add("transform_data_provider");
40+
}
41+
42+
@Override
43+
public void transform(IFactoryAnnotation annotation, Method method) {
44+
logs.add("transform_factory");
45+
}
46+
47+
@Override
48+
public void transform(
49+
IConfigurationAnnotation annotation,
50+
Class testClass,
51+
Constructor testConstructor,
52+
Method testMethod) {
53+
logs.add("transform_configuration");
54+
}
55+
56+
@Override
57+
public void transform(
58+
ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
59+
logs.add("transform_test");
60+
}
61+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package test.listeners.issue2381;
2+
3+
import org.testng.IExecutionListener;
4+
import org.testng.annotations.BeforeClass;
5+
import org.testng.annotations.Listeners;
6+
import org.testng.annotations.Test;
7+
8+
@Listeners(TestClassSample.MyListener.class)
9+
public class TestClassSample {
10+
11+
@BeforeClass
12+
public void beforeClass() {}
13+
14+
@Test
15+
public void testMethod() {}
16+
17+
public static class MyListener implements IExecutionListener {}
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
3+
<suite name="2381_suite" verbose="2">
4+
<listeners>
5+
<listener class-name="test.listeners.issue2381.SampleTransformer"/>
6+
<listener class-name="test.listeners.issue2381.SampleGlobalListener"/>
7+
</listeners>
8+
9+
<test name="2381_test" verbose="2">
10+
<classes>
11+
<class name="test.listeners.issue2381.TestClassSample"/>
12+
<class name="test.listeners.issue2381.FactoryTestClassSample"/>
13+
</classes>
14+
</test>
15+
16+
</suite>
17+

0 commit comments

Comments
 (0)