【问题标题】:How to make a JUnit Test retry in SuiteClass if it fails?如果失败,如何在 SuiteClass 中进行 JUnit 测试重试?
【发布时间】:2019-07-19 21:13:08
【问题描述】:

我有以下 RetryRule 类:

public class RetryRule implements TestRule {
    private int retryCount;

    public RetryRule(int retryCount) {
        this.retryCount = retryCount;
    }

    public Statement apply(Statement base, Description description) {
        return statement(base, description);
    }

    private Statement statement(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                Throwable caughtThrowable = null;

                for (int i = 0; i < retryCount; i++) {
                    try {
                        base.evaluate();
                        return;
                    }
                    catch (Throwable t) {
                        caughtThrowable = t;
                        System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed.");
                    }
                }
                System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures.");
                if (caughtThrowable != null) {
                    throw caughtThrowable;
                }
            }
        };
    }
}

还有以下 SuiteClass:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
MakeBookingTest.class,
PaymentTest.class
})

public class TestSuite {
}

这有两个测试类.. MakeBookingTestPaymentTest。他们每个人都有多个 JUnit 测试。

我希望在它们失败时重试它们。知道如何实现吗?

编辑:为了更好地理解,您可以使用我的代码来举例说明要添加的内容。谢谢。欣赏它。

【问题讨论】:

  • 不要误会我的意思……但是为什么?您希望从重新运行失败的测试中获得什么?
  • 有时它会失败,因为它们可能很脆弱。但是 99% 的时间,如果我重新运行……它会起作用。午夜运行的詹金斯作业运行套件类。因此,理想情况下,它应该重试任何失败的测试。

标签: java unit-testing junit test-suite


【解决方案1】:

首先我同意 GhostCat。
Flakey 测试代码是真正的问题。

但如果“flakeyness”不在您的代码中(例如,与外部 Web 服务的网络连接不良),那么重新运行测试可能会很有用。

在这种情况下,您可以执行以下操作。

首先创建一个接口注解。 (这将用于指示哪些测试需要重试。)

@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {}

然后将TestRule 应用于我们的测试。 (如果存在Retry 注释,此规则将检查失败)

public class RetryRule implements TestRule {
    @Override
    public Statement apply(Statement base, Description method) {
        return new Statement() {
            @Override 
            public void evaluate() throws Throwable {
                try {
                    base.evaluate();
                } catch (Throwable t) {
                    Retry retry = method.getAnnotation(Retry.class);
                    if (retry != null) {
                        base.evaluate();
                    } else {
                        throw t;
                    }
                }
            }
        };
    }
}

最后在我们的测试中,我们把所有东西放在一起

public class RetryTest {
    private static int count = 0;

    @Rule
    public RetryRule rule = new RetryRule();

    @Test
    @Retry
    public void testToRetry() throws Exception {
        callMyFlakeyCode();
    }
}

【讨论】:

  • 非常有趣。问题仍然是,我如何在 SuiteClass 中应用它而不是为每个测试单独应用?正如我上面提到的(带有示例)我的问题中的代码? :)
  • 这应该可以在不触及您的 SuiteClass 的情况下工作。或者您是否尝试重新运行整个 TestClass,即使该 TestClass 中只有一个测试失败?这似乎不是一个很有帮助的行为。
  • 是的,那么我是否将@Rule 添加到每个测试类而不触及SuiteClass?如果我理解正确?我有 55 个测试类...在当前上下文中,我只包括了两个。
  • 是的,将规则添加到 TestClass。并将 Retry 注释添加到您要在该 TestClass 中重新测试的特定测试。
【解决方案2】:

一个明显的非回答,基于给出的评论:

有时它会失败,因为它们可能很脆弱。但是 99% 的时间,如果我重新运行……它会起作用。

在这种情况下,投入您的时间和精力来说服您的测试设置进行“重新运行”......这很可能是一项糟糕的投资。

您的问题不在于重试。你的真正问题是你有不稳定的测试。您投入所有时间和精力来了解您的测试不可靠的原因,然后您修复该问题。

其他任何事情都会无缘无故地增加设置的复杂性。您编写需要维护的特殊代码,更糟糕的是:所有未来的读者都必须理解“是的,这些测试在那里,我们只是重试它们直到它们通过”。这是人们迟早会接受的信息。

【讨论】:

  • 好的,我同意你的建议。调查它们为什么不稳定并修复它是有意义的。不过,您能否就如何重试提供一些意见? - 知道如何在当前上下文中执行它们会很好。
  • @saffik 事情是:这可能需要一些时间坐下来尝试和测试。我现在没有时间 ;-) ...如果我有一个好的技术答案,我会把它包括在内。
  • 一个真实的情况,需要@Retry,其中代码的一部分是脆弱的:我们想要测试一个方法的大约80%的输出是true,而其余的是false ;该方法本身不是确定性的,但我们想要的是一个粗略的正确性(它用于平衡对目标 A 和 B 的大量请求)。在这种情况下,现在我将单个测试的百分比范围调整为[0.77, 0.83],但我发现它太宽泛了。所以我想缩小范围,但增加执行次数,以防万一失败。
  • @WesternGun 谢谢。这是一个有趣的方法。但我想知道我们是否仍在谈论“真正的”单元测试,或者如果这更像是一个功能/集成测试,恰好使用 JUnit 框架;-)
  • 嗯,我同意它更实用;我只想说明,在某些情况下,单次执行的结果不是确定性的,但从统计上讲,该方法会做它应该做的事情。不过,这个案例非常奇特。但是现在我们已经在谈论重试了……我们已经知道有些东西是特殊/不稳定
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 2015-09-01
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多