简体   繁体   English

多线程环境下TestNG重试测试

[英]TestNG retry test in multithreaded environment

I have been using TestNG retry mechanism as following -我一直在使用 TestNG 重试机制如下 -

public class TestRetryAnalyzer implements IRetryAnalyzer {

public static final int MAX_RETRY_COUNT = 3;
private static final AtomicInteger count = new AtomicInteger(MAX_RETRY_COUNT);

public static void resetCount() {
    count.set(MAX_RETRY_COUNT);
}

public int getCount() {
    return count.get();
}

private boolean isRetryAvailable() {
    return (count.get() > 0);
}

@Override
public boolean retry(ITestResult result) {
    boolean retry = false;
    if (isRetryAvailable()) {
        System.out.println("Going to retry test case: " + result.getMethod() + ", " + (((MAX_RETRY_COUNT - count.get()) + 1)) + " out of " + MAX_RETRY_COUNT);
        retry = true;
        count.decrementAndGet();
    }
    return retry;
}

} }

public class TestRetryListener implements IAnnotationTransformer {

@Override
public void transform(final ITestAnnotation annotation, final Class testClass, final Constructor testConstructor,
                      final Method testMethod) {
    IRetryAnalyzer retryAnalyzer = annotation.getRetryAnalyzer();
    if (retryAnalyzer == null) {
        annotation.setRetryAnalyzer(TestRetryAnalyzer.class);
    }
}

and a Test -和测试 -

public class SimpleTest {

private int count = 0;

@Test
public void test() {
    count++;
    if (count % 3 != 0) {
        Assert.fail("Injected Failure");
    }
    count = 0;
}

And testng.xml file -和 testng.xml 文件 -

<suite name="Suite1" verbose="1">
<listeners>
    <listener class-name="main.java.TestRetryListener" />
    <listener class-name="org.uncommons.reportng.HTMLReporter" />
    <listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
</listeners>
<test name="Sample" >
    <classes>
        <class name="main.java.SimpleTest" />
    </classes>
</test>
<test name="Sample2" >
    <classes>
        <class name="main.java.SimpleTest" />
    </classes>
</test>
<test name="Sample3" >
    <classes>
        <class name="main.java.SimpleTest" />
    </classes>
</test>
<test name="Sample4" >
    <classes>
        <class name="main.java.SimpleTest" />
    </classes>
</test>
<test name="Sample5" >
    <classes>
        <class name="main.java.SimpleTest" />
    </classes>
</test>

When I run only one test then retry mechanism works well (1 pass and 2 skipped).当我只运行一个测试时,重试机制运行良好(1 次通过,2 次跳过)。 But when I run 5 tests as mentioned in above testng.xml file then they begin to fail.但是当我运行上面 testng.xml 文件中提到的 5 个测试时,它们开始失败。 Do I run in to concurrency issues without even running tests in parallel?我是否会在没有并行运行测试的情况下遇到并发问题? How do I get rid of it?我该如何摆脱它?

I am using testNG 6.9.10我正在使用 testNG 6.9.10

TestRetryListener is called only one time by TestNG framework so there will be only one instance of TestRetryAnalyzer will be present in the heap. TestNG 框架仅调用一次 TestRetryListener,因此堆中将只存在一个 TestRetryAnalyzer 实例。 Instance variable "count" (instance of AtomicInteger class) is being shared across multiple tests.多个测试共享实例变量“count”(AtomicInteger 类的实例)。 It is not reset to 3 for every test that means AtomicInteger object is instantiated only once and the same reference is used by TestRetryAnalyzer class.对于每个测试,它不会重置为 3,这意味着 AtomicInteger 对象仅实例化一次,并且 TestRetryAnalyzer 类使用相同的引用。

To overcome the above problem, we have to reset the count to 3 after every test.为了克服上述问题,我们必须在每次测试后将计数重置为 3。 To achieve this, you have to make the following changes为此,您必须进行以下更改

public class SimpleTest {

private int count = 0;

@Test
public void test() {
    count++;
    System.out.println("Test Count ... " + count);
    if (count % 4 != 0) {
        Assert.fail("Injected Failure");
    }
    count = 0;
}

@AfterTest
public void afterTest() {
    TestRetryAnalyzer.resetCount();
}

} }

public class TestRetryAnalyzer implements IRetryAnalyzer {公共类 TestRetryAnalyzer 实现了 IRetryAnalyzer {

private static int MAX_RETRY_COUNT = 3;

private static AtomicInteger count = new AtomicInteger(MAX_RETRY_COUNT);

public static void resetCount() {
    count.set(MAX_RETRY_COUNT);
}

private boolean isRetryAvailable() {
    return (count.intValue() > 0);
}

@Override
public boolean retry(ITestResult result) {
    boolean retry = false;
    if (isRetryAvailable()) {
        retry = true;
        count.decrementAndGet();
        System.out.println("Retry Analyzer count is : " + count);
    }
    return retry;
}

} }

Hope this helps :)希望这有帮助:)

I am using a ThreadLocal instance for dealing with this issue.我正在使用ThreadLocal实例来处理这个问题。 This solution works perfectly.该解决方案完美运行。

public class RetryAnalyzer implements IRetryAnalyzer {

    private ThreadLocal<Integer> count = ThreadLocal.withInitial(() -> 0);

    private static final int maxTry = TestRunner.getRunConfig().getRerun();
    private static final Logger logger = LogManager.getLogger(RetryAnalyzer.class);

    @Override
    public synchronized boolean retry(ITestResult result) {
        if (!result.isSuccess()) {                      //Check if test not succeed
            if (count.get() < maxTry) {                 //Check if maxtry count is reached
                count.set(count.get() + 1);             //Increase the maxTry count by 1
                result.setStatus(ITestResult.FAILURE);  //Mark test as failed
                logger.debug("Now going to retry " + result.getMethod().getMethodName());
                logger.debug("Retry count is " + count);
                return true;                            //Tells TestNG to re-run the test
            } else {
                result.setStatus(ITestResult.FAILURE);  //If maxCount reached,test marked as failed
                count.set(0);                           //Reset count to 0 for next set of tests
                logger.debug("Reset the retry count for " + result.getMethod().getMethodName());
            }
        } else {
            result.setStatus(ITestResult.SUCCESS);      //If test passes, TestNG marks it as passed
        }
        return false;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM