Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline AfterClass invocation #2757

Merged
merged 1 commit into from May 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.txt
@@ -1,5 +1,6 @@
Current
7.6.0
Fixed: GITHUB-2726: @AfterClass config method is executed for EACH @Test method when parallel == methods (Krishnan Mahadevan)
Fixed: GITHUB-2752: TestListener is being lost when implenting both IClassListener and ITestListener (Krishnan Mahadevan)
New: GITHUB-2724: DataProvider: possibility to unload dataprovider class, when done with it (Dzmitry Sankouski)
Fixed: GITHUB-217: Configure TestNG to fail when there's a failure in data provider (Krishnan Mahadevan)
Expand Down
3 changes: 2 additions & 1 deletion testng-core/src/main/java/org/testng/ClassMethodMap.java
Expand Up @@ -51,7 +51,8 @@ public ClassMethodMap(List<ITestNGMethod> methods, XmlMethodSelector xmlMethodSe
public boolean removeAndCheckIfLast(ITestNGMethod m, Object instance) {
Collection<ITestNGMethod> l = classMap.get(instance);
if (l == null) {
throw new AssertionError("l should not be null");
throw new IllegalStateException(
"Could not find any methods associated with test class instance " + instance);
}
l.remove(m);
// It's the last method of this class if all the methods remaining in the list belong to a
Expand Down
Expand Up @@ -127,7 +127,9 @@ && doesTaskHavePreRequistes()
try {
invokeTestMethods(testMethod, testMthdInst.getInstance());
} finally {
invokeAfterClassMethods(testMethod.getTestClass(), testMthdInst);
synchronized (testMethod.getInstance()) {
invokeAfterClassMethods(testMethod.getTestClass(), testMthdInst);
}
}
}
}
Expand Down
@@ -1,9 +1,13 @@
package test.configuration;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Arrays;
import org.testng.Assert;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.testng.xml.XmlSuite;
import test.configuration.issue2726.TestClassSample;
import test.configuration.issue2743.SuiteRunnerIssueTestSample;
import test.configuration.sample.ConfigurationTestSample;
import test.configuration.sample.ExternalConfigurationClassSample;
Expand Down Expand Up @@ -39,4 +43,14 @@ public void testSuiteRunnerWithDefaultConfiguration() {

Assert.assertEquals(testNG.getStatus(), 0);
}

@Test(description = "GITHUB-2726")
public void testAfterClassCalledOnlyOnceForParallelTestMethods() {
TestNG testng = create(TestClassSample.class);
testng.setParallel(XmlSuite.ParallelMode.METHODS);
testng.setVerbose(2);
testng.run();
assertThat(TestClassSample.beforeLogs).hasSize(1);
assertThat(TestClassSample.afterLogs).hasSize(1);
}
}
@@ -0,0 +1,29 @@
package test.configuration.issue2726;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class TestClassSample {

public static final List<String> beforeLogs = new CopyOnWriteArrayList<>();
public static final List<String> afterLogs = new CopyOnWriteArrayList<>();

@BeforeClass
public void setup() {
beforeLogs.add("BEFORE_" + Thread.currentThread().getName());
}

@AfterClass
public void tearDown() {
afterLogs.add("AFTER_" + Thread.currentThread().getName());
}

@Test
public void testA() {}

@Test
public void testB() {}
}