From 5cffe02b91cacfa9253aac44dae4b6645164efad Mon Sep 17 00:00:00 2001 From: Pavel Sakharchuk <60096114+PavelSakharchuk@users.noreply.github.com> Date: Tue, 13 Apr 2021 16:18:06 +0300 Subject: [PATCH] Handling invocation-number to xml for DataProvider + Factory (#2516) Closes #2517 --- CHANGES.txt | 1 + .../org/testng/internal/FactoryMethod.java | 7 ++- .../org/testng/internal/IParameterInfo.java | 5 ++ .../org/testng/internal/ParameterInfo.java | 9 ++- .../testng/internal/invokers/TestInvoker.java | 9 ++- ...oviderWithFactoryFailedReporterSample.java | 28 ++++++++++ ...ProviderWithFactoryFailedReporterTest.java | 55 +++++++++++++++++++ core/src/test/resources/testng.xml | 1 + 8 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterSample.java create mode 100644 core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterTest.java diff --git a/CHANGES.txt b/CHANGES.txt index 9e15d39dc3..0b1c1d4cd7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ Current +Fixed: GITHUB-2517: Factory data-provider parameters not displayed in 'testng-failed.xml' file (Pavel Sakharchuk) Fixed: GITHUB-279: Guice dependency injection into listeners and reporters (Krishnan Mahadevan) Fixed: GITHUB-2504: Data provider data cannot be populated to onTestStart hook when BeforeMethod is failed (Krishnan Mahadevan) Fixed: GITHUB-2489: Hierarchical base- and test-class @AfterClass methods out of order using groups (Krishnan Mahadevan) diff --git a/core/src/main/java/org/testng/internal/FactoryMethod.java b/core/src/main/java/org/testng/internal/FactoryMethod.java index 265216ba05..e0e41bc16e 100644 --- a/core/src/main/java/org/testng/internal/FactoryMethod.java +++ b/core/src/main/java/org/testng/internal/FactoryMethod.java @@ -181,14 +181,15 @@ public IParameterInfo[] invoke() { com.getDeclaringClass().getName(), com.getName()); } if (indices == null || indices.isEmpty()) { + int finalPosition = position; result.addAll(Arrays.stream(testInstances).map(instance -> - new ParameterInfo(instance, parameters) + new ParameterInfo(instance, finalPosition, parameters) ).collect(Collectors.toList())); } else { for (Integer index : indices) { int i = index - position; if (i >= 0 && i < testInstances.length) { - result.add(new ParameterInfo(testInstances[i], parameters)); + result.add(new ParameterInfo(testInstances[i], position, parameters)); } } } @@ -196,7 +197,7 @@ public IParameterInfo[] invoke() { } else { if (indices == null || indices.isEmpty() || indices.contains(position)) { Object instance = m_objectFactory.newInstance(com.getConstructor(), parameters); - result.add(new ParameterInfo(instance, parameters)); + result.add(new ParameterInfo(instance, position, parameters)); } position++; } diff --git a/core/src/main/java/org/testng/internal/IParameterInfo.java b/core/src/main/java/org/testng/internal/IParameterInfo.java index 6a9736ee13..227fdae8c0 100644 --- a/core/src/main/java/org/testng/internal/IParameterInfo.java +++ b/core/src/main/java/org/testng/internal/IParameterInfo.java @@ -10,6 +10,11 @@ public interface IParameterInfo { */ Object getInstance(); + /** + * @return - The actual index of instance associated with a factory method + */ + int getIndex(); + /** * @return - The parameters associated with the factory method as an array. */ diff --git a/core/src/main/java/org/testng/internal/ParameterInfo.java b/core/src/main/java/org/testng/internal/ParameterInfo.java index 02de99d295..7b514d1da4 100644 --- a/core/src/main/java/org/testng/internal/ParameterInfo.java +++ b/core/src/main/java/org/testng/internal/ParameterInfo.java @@ -2,10 +2,12 @@ public class ParameterInfo implements IParameterInfo { private Object instance; + private final int index; private Object[] parameters; - public ParameterInfo(Object instance, Object[] parameters) { + public ParameterInfo(Object instance, int index, Object[] parameters) { this.instance = instance; + this.index = index; this.parameters = parameters; } @@ -14,6 +16,11 @@ public Object getInstance() { return instance; } + @Override + public int getIndex() { + return index; + } + @Override public Object[] getParameters() { return parameters; diff --git a/core/src/main/java/org/testng/internal/invokers/TestInvoker.java b/core/src/main/java/org/testng/internal/invokers/TestInvoker.java index 3a248c8e2e..6d91226b1e 100644 --- a/core/src/main/java/org/testng/internal/invokers/TestInvoker.java +++ b/core/src/main/java/org/testng/internal/invokers/TestInvoker.java @@ -634,9 +634,14 @@ private ITestResult invokeMethod( // that it has parameters, so might have to revisit this if bugs get reported // for the case where this method has parameters that don't come from a data // provider - if (testResult.getThrowable() != null && arguments.getParameterValues().length > 0) { + if (testResult.getThrowable() != null && + (arguments.getParameterValues().length > 0 || testResult.getFactoryParameters().length > 0)) { + int parametersIndex = arguments.getParametersIndex(); + if (null != testResult.getMethod().getFactoryMethodParamsInfo()) { + parametersIndex = testResult.getMethod().getFactoryMethodParamsInfo().getIndex(); + } arguments.getTestMethod() - .addFailedInvocationNumber(arguments.getParametersIndex()); + .addFailedInvocationNumber(parametersIndex); } // diff --git a/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterSample.java b/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterSample.java new file mode 100644 index 0000000000..57a9e8e0d7 --- /dev/null +++ b/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterSample.java @@ -0,0 +1,28 @@ +package test.failedreporter.issue2517; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +public class DataProviderWithFactoryFailedReporterSample { + private Integer data; + + @Factory(dataProvider = "dp") + public DataProviderWithFactoryFailedReporterSample(Integer data) { + this.data = data; + } + + @DataProvider + public static Object[][] dp() { + return new Object[][]{ + new Object[]{0}, new Object[]{1}, new Object[]{2}, + }; + } + + @Test + public void f1() { + if (data == 1) { + throw new RuntimeException(); + } + } +} diff --git a/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterTest.java b/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterTest.java new file mode 100644 index 0000000000..d0a7f9ccac --- /dev/null +++ b/core/src/test/java/test/failedreporter/issue2517/DataProviderWithFactoryFailedReporterTest.java @@ -0,0 +1,55 @@ +package test.failedreporter.issue2517; + +import org.testng.Assert; +import org.testng.TestNG; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.testng.collections.Lists; +import test.SimpleBaseTest; + +import java.io.File; +import java.util.List; + +public class DataProviderWithFactoryFailedReporterTest extends SimpleBaseTest { + private File mTempDirectory; + + @BeforeMethod + public void setUp() { + mTempDirectory = createDirInTempDir("testng-tmp-" + System.currentTimeMillis() % 1000); + } + + @AfterMethod + public void tearDown() { + deleteDir(mTempDirectory); + } + + @Test + public void failedMethodWithDataProviderAndFactoryShouldHaveInvocationNumbers() { + testFailedReporter( + new String[]{"f1"}, + "", + DataProviderWithFactoryFailedReporterSample.class); + } + + private void testFailedReporter(String[] expectedMethods, String expectedLine, Class... cls) { + triggerTest(cls); + runAssertions(mTempDirectory, expectedMethods, expectedLine, 1); + } + + private void triggerTest(Class... cls) { + TestNG tng = create(mTempDirectory.toPath(), cls); + tng.setUseDefaultListeners(true); + tng.run(); + } + + private static void runAssertions( + File outputDir, String[] expectedMethods, String expectedLine, int expected) { + File failed = new File(outputDir, "testng-failed.xml"); + for (String s : expectedMethods) { + List resultLines = Lists.newArrayList(); + grep(failed, String.format(expectedLine, s), resultLines); + Assert.assertEquals(resultLines.size(), expected); + } + } +} diff --git a/core/src/test/resources/testng.xml b/core/src/test/resources/testng.xml index 5072df91a9..4dce8eb9b5 100644 --- a/core/src/test/resources/testng.xml +++ b/core/src/test/resources/testng.xml @@ -132,6 +132,7 @@ +