Skip to content

Commit

Permalink
Streamline data provider listener invocation
Browse files Browse the repository at this point in the history
  • Loading branch information
krmahadevan committed Feb 7, 2024
1 parent 4af6e94 commit 8770d6a
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Current
7.10.0
Fixed: GITHUB-3045: IDataProviderListener - beforeDataProviderExecution and afterDataProviderExecution are called twice in special setup (Krishnan Mahadevan)
Fixed: GITHUB-3038: java.lang.IllegalStateException: Results per method should NOT have been empty (Krishnan Mahadevan)
Fixed: GITHUB-3022: Remove deprecated JUnit related support in TestNG (Krishnan Mahadevan)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.testng.DataProviderHolder;
import org.testng.IClassListener;
Expand Down Expand Up @@ -265,13 +267,23 @@ public void runTestResultListener(ITestResult tr) {
tr, Collections.singletonList(m_notifier.getExitCodeListener()));
}

private static String className(IDataProviderListener listener) {
return listener.getClass().getName();
}

private Collection<IDataProviderListener> dataProviderListeners() {
ISuite suite = this.m_testContext.getSuite();
Collection<IDataProviderListener> dpListeners = Sets.newHashSet(this.holder.getListeners());
BinaryOperator<IDataProviderListener> merger = (l1, l2) -> l1;
Map<String, IDataProviderListener> data =
this.holder.getListeners().stream()
.collect(Collectors.toMap(TestInvoker::className, Function.identity(), merger));
Collection<IDataProviderListener> dpListeners = Sets.newHashSet(data.values());
if (suite instanceof SuiteRunner) {
Collection<IDataProviderListener> listeners =
((SuiteRunner) suite).getDataProviderListeners();
dpListeners.addAll(listeners);
listeners.stream()
.filter(it -> !data.containsKey(it.getClass().getName()))
.forEach(dpListeners::add);
}
return dpListeners;
}
Expand Down
47 changes: 47 additions & 0 deletions testng-core/src/test/java/test/dataprovider/DataProviderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.testng.internal.collections.Pair;
import org.testng.internal.reflect.MethodMatcherException;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
import test.InvokedMethodNameListener;
import test.SimpleBaseTest;
Expand Down Expand Up @@ -54,6 +56,9 @@
import test.dataprovider.issue2934.TestCaseSample.CoreListener;
import test.dataprovider.issue2934.TestCaseSample.ToggleDataProvider;
import test.dataprovider.issue2980.LoggingListener;
import test.dataprovider.issue3045.DataProviderListener;
import test.dataprovider.issue3045.DataProviderTestClassSample;
import test.dataprovider.issue3045.DataProviderWithoutListenerTestClassSample;

public class DataProviderTest extends SimpleBaseTest {

Expand Down Expand Up @@ -666,6 +671,48 @@ public Object[][] getSuiteFileNames() {
};
}

@Test(description = "GITHUB-3045")
public void testIfDataProviderListenerInvokedOnlyOncePerDataProvider() {
runTest(DataProviderTestClassSample.class, "");
}

@Test(description = "GITHUB-3045")
public void testIfDataProviderListenerInvokedOnlyOncePerDataProviderWhenListenerAddedViaSuite() {
runTest(DataProviderWithoutListenerTestClassSample.class, DataProviderListener.class.getName());
}

private static void runTest(Class<?> clazz, String listener) {
DataProviderListener.logs.clear();
TestNG testng = new TestNG();
XmlSuite xmlSuite = new XmlSuite();
if (!listener.isEmpty()) {
xmlSuite.addListener(DataProviderListener.class.getName());
}
xmlSuite.setName("suite1");
xmlTest(xmlSuite, clazz, "Test1", "normalTest");
xmlTest(xmlSuite, clazz, "Test2", "dataDrivenTest");
testng.setXmlSuites(Collections.singletonList(xmlSuite));
testng.setVerbose(2);
testng.run();
assertThat(DataProviderListener.logs).hasSize(2);
assertThat(DataProviderListener.logs)
.containsExactly(
"[Test2]-beforeDataProviderExecution-dataProvider",
"[Test2]-afterDataProviderExecution-dataProvider");
}

private static void xmlTest(XmlSuite xmlSuite, Class<?> clazz, String name, String methodName) {
XmlTest xmlTest = new XmlTest(xmlSuite);
xmlTest.setName(name);
xmlTest.setXmlClasses(List.of(xmlClass(clazz, methodName)));
}

private static XmlClass xmlClass(Class<?> clazz, String methodName) {
XmlClass xmlClass = new XmlClass(clazz);
xmlClass.setIncludedMethods(List.of(new XmlInclude(methodName)));
return xmlClass;
}

private LoggingListener runDataProviderTest(boolean flag) {
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] {test.dataprovider.issue2980.TestClassSample.class});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package test.dataprovider.issue3045;

import java.util.ArrayList;
import java.util.List;
import org.testng.IDataProviderListener;
import org.testng.IDataProviderMethod;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;

public class DataProviderListener implements IDataProviderListener {

public static List<String> logs = new ArrayList<>();

@Override
public void beforeDataProviderExecution(
IDataProviderMethod dataProviderMethod, ITestNGMethod method, ITestContext iTestContext) {
logs.add(
testName(iTestContext)
+ "-beforeDataProviderExecution-"
+ dataProviderMethod.getMethod().getName());
}

@Override
public void afterDataProviderExecution(
IDataProviderMethod dataProviderMethod, ITestNGMethod method, ITestContext iTestContext) {
logs.add(
testName(iTestContext)
+ "-afterDataProviderExecution-"
+ dataProviderMethod.getMethod().getName());
}

private String testName(ITestContext ctx) {
return "[" + ctx.getName() + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package test.dataprovider.issue3045;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners({DataProviderListener.class})
public class DataProviderTestClassSample {

@DataProvider
public Object[][] dataProvider() {
return new Object[][] {{"Test_1"}, {"Test_2"}, {"Test_3"}};
}

@Test(dataProvider = "dataProvider")
public void dataDrivenTest(String ignored) {}

@Test
public void normalTest() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package test.dataprovider.issue3045;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderWithoutListenerTestClassSample {

@DataProvider
public Object[][] dataProvider() {
return new Object[][] {{"Test_1"}, {"Test_2"}, {"Test_3"}};
}

@Test(dataProvider = "dataProvider")
public void dataDrivenTest(String ignored) {}

@Test
public void normalTest() {}
}

0 comments on commit 8770d6a

Please sign in to comment.