为了账号安全,请及时绑定邮箱和手机立即绑定

如何立即重新运行失败的JUnit测试?

如何立即重新运行失败的JUnit测试?

泛舟湖上清波郎朗 2019-08-12 18:02:41
如何立即重新运行失败的JUnit测试?有没有办法让JUnit规则或类似的东西给每个失败的测试提供第二次机会,只需尝试再次运行它。背景:我有一大堆用JUnit编写的Selenium2-WebDriver测试。由于非常激进的时间(点击后只有短暂的等待时间),一些测试(100个中的1个,总是不同的测试)可能会失败,因为服务器有时响应速度稍慢。但我不能让等待时间太久以至于它肯定足够长,因为那时测试将永远持续下去。) - 所以我认为这个用例即使需要一秒钟,测试也是绿色的是可以接受的尝试。当然,最好有3个中的2个(重复3次失败的测试,如果其中两个测试是正确的,则将它们视为正确),但这将是未来的改进。
查看完整描述

3 回答

?
MM们

TA贡献1886条经验 获得超2个赞

至于我编写自定义转轮更灵活的解决方案。上面发布的解决方案(带代码示例)有两个缺点:

  1. 如果它在@BeforeClass阶段失败,它将不会重试测试;

  2. 它计算测试的运行方式有点不同(当你有3次重试时,你将收到测试运行:4,成功1可能会令人困惑);

这就是为什么我更喜欢写自定义跑步者的方法。自定义运行程序的代码可能如下:

import org.junit.Ignore;import org.junit.internal.AssumptionViolatedException;import org.junit.internal.runners.model.EachTestNotifier;import org.junit.runner.Description;import org.junit.runner.notification.RunNotifier;import org.junit.runner.notification.StoppedByUserException;import org.junit.runners.BlockJUnit4ClassRunner;import org.junit.runners.model.FrameworkMethod;import org.junit.runners.model.InitializationError;import org.junit.runners.model.Statement;public class RetryRunner extends BlockJUnit4ClassRunner {

    private final int retryCount = 100;
    private int failedAttempts = 0;

    public RetryRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }    


    @Override
    public void run(final RunNotifier notifier) {
        EachTestNotifier testNotifier = new EachTestNotifier(notifier,
                getDescription());
        Statement statement = classBlock(notifier);
        try {

            statement.evaluate();
        } catch (AssumptionViolatedException e) {
            testNotifier.fireTestIgnored();
        } catch (StoppedByUserException e) {
            throw e;
        } catch (Throwable e) {
            retry(testNotifier, statement, e);
        }
    }

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description = describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else {
            runTestUnit(methodBlock(method), description, notifier);
        }
    }

    /**
     * Runs a {@link Statement} that represents a leaf (aka atomic) test.
     */
    protected final void runTestUnit(Statement statement, Description description,
            RunNotifier notifier) {
        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
        eachNotifier.fireTestStarted();
        try {
            statement.evaluate();
        } catch (AssumptionViolatedException e) {
            eachNotifier.addFailedAssumption(e);
        } catch (Throwable e) {
            retry(eachNotifier, statement, e);
        } finally {
            eachNotifier.fireTestFinished();
        }
    }

    public void retry(EachTestNotifier notifier, Statement statement, Throwable currentThrowable) {
        Throwable caughtThrowable = currentThrowable;
        while (retryCount > failedAttempts) {
            try {
                statement.evaluate();
                return;
            } catch (Throwable t) {
                failedAttempts++;
                caughtThrowable = t;
            }
        }
        notifier.addFailure(caughtThrowable);
    }}


查看完整回答
反对 回复 2019-08-12
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

在有一个更好的选择。如果您正在使用maven插件,例如:surfire或failsefe,则可以选择添加参数rerunFailingTestsCount SurFire Api。这些东西在以下票证中实现:Jira Ticket。在这种情况下,您不需要编写自定义代码和插件自动修改测试结果报告。
我看到这种方法只有一个缺点:如果某些测试失败,则在课前/课后阶段测试将不会重新运行。

查看完整回答
反对 回复 2019-08-12
  • 3 回答
  • 0 关注
  • 908 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信