Skip to content

Commit 2df9518

Browse files
committed
Unexpected test runs count with retry analyzer
Closes #2798
1 parent bfdaf6d commit 2df9518

File tree

5 files changed

+65
-18
lines changed

5 files changed

+65
-18
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ New: Ability to provide custom error message for assertThrows\expectThrows metho
44
Fixed: GITHUB-2780: Use SpotBugs instead of abandoned FindBugs
55
Fixed: GITHUB-2801: JUnitReportReporter is too slow
66
Fixed: GITHUB-2807: buildStackTrace should be fail-safe
7+
Fixed: GITHUB-2798: Parallel executions coupled with retry analyzer results in duplicate retry analyzer instances being created (Krishnan Mahadevan)
78

89
7.6.1
910
Fixed: GITHUB-2761: Exception: ERROR java.nio.file.NoSuchFileException: /tmp/testngXmlPathInJar-15086412835569336174 (Krishnan Mahadevan)

testng-core/src/main/java/org/testng/internal/BaseTestMethod.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public abstract class BaseTestMethod implements ITestNGMethod, IInvocationStatus
5858
private boolean m_enabled;
5959

6060
private final String m_methodName;
61-
// If a depended group is not found
61+
// If a depends on group is not found
6262
private String m_missingGroup;
6363
private String m_description = null;
6464
protected AtomicInteger m_currentInvocationCount = new AtomicInteger(0);
@@ -449,10 +449,6 @@ protected IAnnotationFinder getAnnotationFinder() {
449449
return m_annotationFinder;
450450
}
451451

452-
protected IClass getIClass() {
453-
return m_testClass;
454-
}
455-
456452
static StringBuilder stringify(String cls, ConstructorOrMethod method) {
457453
StringBuilder result = new StringBuilder(cls).append(".").append(method.getName()).append("(");
458454
return result.append(method.stringifyParameterTypes()).append(")");
@@ -788,16 +784,13 @@ private IRetryAnalyzer getRetryAnalyzerConsideringMethodParameters(ITestResult t
788784
return this.m_retryAnalyzer;
789785
}
790786
final String keyAsString = getSimpleName() + "#" + getParameterInvocationCount();
791-
final IRetryAnalyzer currentRetryAnalyzerInMap = m_testMethodToRetryAnalyzer.get(keyAsString);
792-
if (currentRetryAnalyzerInMap != null) {
793-
return currentRetryAnalyzerInMap;
794-
}
795-
BasicAttributes ba = new BasicAttributes(null, this.m_retryAnalyzerClass);
796-
CreationAttributes attributes = new CreationAttributes(tr.getTestContext(), ba, null);
797-
IRetryAnalyzer instance =
798-
(IRetryAnalyzer) Dispenser.newInstance(m_objectFactory).dispense(attributes);
799-
m_testMethodToRetryAnalyzer.put(keyAsString, instance);
800-
return instance;
787+
return m_testMethodToRetryAnalyzer.computeIfAbsent(
788+
keyAsString,
789+
key -> {
790+
BasicAttributes ba = new BasicAttributes(null, this.m_retryAnalyzerClass);
791+
CreationAttributes attributes = new CreationAttributes(tr.getTestContext(), ba, null);
792+
return (IRetryAnalyzer) Dispenser.newInstance(m_objectFactory).dispense(attributes);
793+
});
801794
}
802795

803796
private static boolean isNotParameterisedTest(ITestResult tr) {

testng-core/src/test/java/test/retryAnalyzer/RetryAnalyzerTest.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.List;
99
import java.util.Map;
1010
import java.util.Set;
11+
import java.util.function.Function;
1112
import java.util.stream.Collectors;
1213
import org.testng.Assert;
1314
import org.testng.ITestResult;
@@ -22,7 +23,6 @@
2223
import test.SimpleBaseTest;
2324
import test.retryAnalyzer.dataprovider.issue2163.TestClassPoweredByDataProviderSample;
2425
import test.retryAnalyzer.github1519.MyListener;
25-
import test.retryAnalyzer.github1519.TestClassSample;
2626
import test.retryAnalyzer.github1600.Github1600Listener;
2727
import test.retryAnalyzer.github1600.Github1600TestSample;
2828
import test.retryAnalyzer.github1706.DataDrivenSample;
@@ -38,8 +38,20 @@
3838
import test.retryAnalyzer.issue1946.TestclassSample1;
3939
import test.retryAnalyzer.issue1946.TestclassSample2;
4040
import test.retryAnalyzer.issue2684.SampleTestClassWithGroupConfigs;
41+
import test.retryAnalyzer.issue2798.HashCodeAwareRetryAnalyzer;
42+
import test.retryAnalyzer.issue2798.TestClassSample;
4143

4244
public class RetryAnalyzerTest extends SimpleBaseTest {
45+
46+
@Test(description = "GITHUB-2798")
47+
public void ensureNoDuplicateRetryAnalyzerInstancesAreCreated() {
48+
create(TestClassSample.class).run();
49+
Map<Integer, Long> collected =
50+
HashCodeAwareRetryAnalyzer.hashCodes.stream()
51+
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
52+
assertThat(collected.keySet()).hasSize(1);
53+
}
54+
4355
@Test
4456
public void testInvocationCounts() {
4557
TestNG tng = create(InvocationCountTest.class);
@@ -61,10 +73,10 @@ public void testInvocationCounts() {
6173

6274
@Test
6375
public void testIfRetryIsInvokedBeforeListener() {
64-
TestNG tng = create(TestClassSample.class);
76+
TestNG tng = create(test.retryAnalyzer.github1519.TestClassSample.class);
6577
tng.addListener(new MyListener());
6678
tng.run();
67-
assertThat(TestClassSample.messages)
79+
assertThat(test.retryAnalyzer.github1519.TestClassSample.messages)
6880
.containsExactly("afterInvocation", "retry", "afterInvocation");
6981
}
7082

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package test.retryAnalyzer.issue2798;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import org.testng.IRetryAnalyzer;
6+
import org.testng.ITestResult;
7+
8+
public class HashCodeAwareRetryAnalyzer implements IRetryAnalyzer {
9+
10+
public static final List<Integer> hashCodes = new ArrayList<>();
11+
12+
int cnt = 0;
13+
static final int threshold = 2;
14+
15+
@Override
16+
public synchronized boolean retry(ITestResult result) {
17+
hashCodes.add(this.hashCode());
18+
return cnt++ < threshold;
19+
}
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package test.retryAnalyzer.issue2798;
2+
3+
import java.io.FileNotFoundException;
4+
import java.io.IOException;
5+
import java.util.Arrays;
6+
import java.util.Iterator;
7+
import org.testng.annotations.DataProvider;
8+
import org.testng.annotations.Test;
9+
10+
public class TestClassSample {
11+
12+
@DataProvider(name = "test data", parallel = true)
13+
public Iterator<Object[]> data() {
14+
return Arrays.asList(new Object[] {"1"}, new Object[] {"2"}).iterator();
15+
}
16+
17+
@Test(dataProvider = "test data", retryAnalyzer = HashCodeAwareRetryAnalyzer.class)
18+
public void foo(String ignored) throws IOException {
19+
throw new FileNotFoundException("this can be retried");
20+
}
21+
}

0 commit comments

Comments
 (0)