package test.testng1396;
import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.testng.collections.Lists;
import org.testng.xml.XmlSuite;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static org.testng.Assert.fail;
public class ParallelByInstancesInterceptorTest {
@Test(description = "test for https://github.com/cbeust/testng/issues/1396")
public void should_honor_interceptor_order_when_running_parallel_instances() {
TestNG tng = new TestNG();
tng.setVerbose(0);
// 10 instances is enough that we see the non-deterministic ordering of hashmaps more often than not
tng.setTestClasses(new Class[]{
SampleFor1396.Sample9For1396.class,
SampleFor1396.Sample8For1396.class,
SampleFor1396.Sample7For1396.class,
SampleFor1396.Sample6For1396.class,
SampleFor1396.Sample5For1396.class,
SampleFor1396.Sample4For1396.class,
SampleFor1396.Sample3For1396.class,
SampleFor1396.Sample2For1396.class,
SampleFor1396.Sample1For1396.class,
SampleFor1396.Sample0For1396.class
});
// bug only exists when running parallel by instances with this flag set to false
tng.setParallel(XmlSuite.ParallelMode.INSTANCES);
tng.setPreserveOrder(false);
// thread count of 1 forces sequential execution so we can verify ordering
tng.setThreadCount(1);
TestListenerAdapter adapter = new TestListenerAdapter();
tng.addListener(adapter);
// Runs tests annotated with @TestNG1396HighPriority before tests without it
ReverseOrderTestInterceptor listener = new ReverseOrderTestInterceptor();
tng.addListener(listener);
tng.run();
List<ITestResult> passedTests = adapter.getPassedTests();
boolean lowPrioritySeen = false;
for (ITestResult testResult : passedTests) {
if (isHighPriority(testResult.getMethod())) {
if (lowPrioritySeen) {
fail("high priority should be first");
}
} else {
lowPrioritySeen = true;
}
}
}
private static boolean isHighPriority(IMethodInstance instance) {
return instance.getInstance().getClass().getAnnotation(TestNG1396HighPriority.class) != null;
}
private static boolean isHighPriority(ITestNGMethod method) {
return method.getInstance().getClass().getAnnotation(TestNG1396HighPriority.class) != null;
}
public class ReverseOrderTestInterceptor implements IMethodInterceptor {
@Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
List<IMethodInstance> sorted = Lists.newArrayList(methods);
Collections.sort(sorted, new PriorityComparator());
return sorted;
}
}
public class PriorityComparator implements Comparator<IMethodInstance> {
@Override
public int compare(IMethodInstance o1, IMethodInstance o2) {
if (isHighPriority(o1)) {
if (isHighPriority(o2)) {
return compareMethodNames(o1, o2);
}
return -1;
}
if (isHighPriority(o2)) {
return 1;
}
return compareMethodNames(o1, o2);
}
private int compareMethodNames(IMethodInstance o1, IMethodInstance o2) {
return o2.getMethod().getQualifiedName().compareTo(o1.getMethod().getQualifiedName());
}
}
}