【问题标题】:Junit Implement Execution condition for programatically disabling a test functionJunit实现以编程方式禁用测试功能的执行条件
【发布时间】:2018-10-04 20:18:30
【问题描述】:

我正在尝试构建一个自定义注释以与 JUnit 测试类一起使用。目标是定期运行测试。

要运行的示例类:TempTest.java

  @Periodic(period = 2)
  public class TempTest {
    @Test
    @ExtendWith(PeriodicEnabling.class)
    public void testTrue() {
        assertTrue(true);
    }

    @Test
    @ExtendWith(PeriodicEnabling.class)
    public void testZero() {
        int val = 0; assertEquals(0, val);
    }

    @Test
    @ExtendWith(PeriodicEnabling.class)
    public void testZero2() {
        assertEquals(0, "".length());
    }

    @Test
    @ExtendWith(PeriodicEnabling.class)
    public void testFalse() {
        assertTrue(!false);
    }
 }

所以对于period = 2,我们只想运行每隔一个(或每个第二个)测试。自定义注解如下所示:

@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(PeriodicEnabling.class)
@Target(ElementType.TYPE)
public @interface Periodic {
    int period() default 1;
}

最后是 PeriodicEnabling 辅助类:

public class PeriodicEnabling implements ExecutionCondition {
    private int period, currCount;

    private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled("Count looks good!");
    private static final ConditionEvaluationResult DISABLED = ConditionEvaluationResult.disabled("Disabled due to periodic disabling!");

    public PeriodicEnabling() {
        System.out.println("Constructor!!");

        Class<TempTest> cls = TempTest.class;

        if(cls.isAnnotationPresent(Periodic.class)) {
            Annotation annotation = cls.getAnnotation(Periodic.class);
            this.period = ((Periodic) annotation).period();
        } else {
            this.period = 1;
        }

        currCount = 0;
    }

    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext) {
        System.out.println("before::currCount = " + currCount);

        currCount++;

        int result = this.currCount % this.period;

        if (result == 0) {
            System.out.println("after::enabled::currCount = " + currCount);
            return ENABLED;
        }

        System.out.println("after::disabled::currCount = " + currCount + ", result=" + result);
        return DISABLED;
    }

}

问题:

问题是在第一个测试函数的evaluateExecutionCondition 返回EvaluationCondition.Disabled 之后,其余函数不再为它们执行evaluateExecutionCondition 函数。其余的测试用例根本不运行。

这是我在运行示例测试文件时看到的输出:

Constructor!! 

before::currCount = 0
after::disabled::currCount = 1, result=1

Disabled due to periodic disabling!

Disabled due to periodic disabling!

Disabled due to periodic disabling!

Disabled due to periodic disabling!

我看到了一些解决方案,其中解决方案是使用 assumeThat 函数,其中包含一些动态条件。但是我需要一些不同的东西,我需要一个自定义注解类来处理注解类中每个测试函数的执行。

任何帮助表示赞赏:)!

【问题讨论】:

  • 我建议查看 JUint RunListener 以处理是否应执行测试方法/类和 BlockJUnit4ClassRunner 以便您可以将侦听器应用于被测类。可能还有其他方法,但我认为这是一个好的开始。

标签: java testing junit junit5


【解决方案1】:

您正在将扩展应用于类,因此它不仅对各个方法有效,而且对类本身也有效。 Jupiter 然后尽职尽责地调用evaluateExecutionCondition 来确定该类是否被禁用。既然如此,单独的方法也会被禁用而无需进一步调用。

您的代码中还有一些其他改进(例如,您不应该在扩展中包含字段) - 我建议阅读JUnit 5 extension model 上的阅读内容(链接到我博客上的帖子)。

【讨论】:

  • 非常感谢@Nicolai!作为我对这个问题的研究的一部分,我已经关注了你的博客文章。我尝试遵循您的方法,即使用回调(beforeEachCallBack 和 afterEachCallback) - 但我发现我存储在“ExtensionContext.Store”中的“count”变量的值已为每个方法重新初始化。难道我们不能在所有测试方法之间共享 Store 中的公共数据,并根据该值决定是否执行或跳过该方法?
  • 要跨方法存储您需要的东西,不要将其放入测试方法上下文的存储中。而是询问其父级(这是测试类的上下文)并使用该存储。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多