有条件地忽略JUnit 4中的测试


365

好的,因此@Ignore注释非常适合标记不应运行测试用例。

但是,有时我想忽略基于运行时信息的测试。例如,如果我有一个并发测试需要在具有一定数量内核的计算机上运行。如果此测试是在单处理器计算机上运行的,那么我认为仅通过测试是不正确的(因为尚未运行),并且通过测试并破坏构建肯定不是正确的选择。

因此,我希望能够在运行时忽略测试,因为这似乎是正确的结果(因为测试框架将允许构建通过,但记录未运行测试)。我相当确定注释不会给我这种灵活性,并且怀疑我需要为相关类手动创建测试套件。但是,文档中没有提及任何内容,并且通过API查看还不清楚如何以编程方式完成此操作(即,如何以编程方式创建Test@Ignore注释所创建的实例相同的实例或类似实例?)。

如果有人在过去做过类似的事情,或者对我还能做些什么有一个聪明的主意,那么我很乐意听到。

Answers:


476

JUnit的方法是在运行时执行此操作org.junit.Assume

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

您可以在@Before方法中或在测试本身中进行操作,但不能在@After方法中进行。如果您在测试本身中执行此操作,则您的@Before方法将运行。您也可以在内部执行此操作@BeforeClass以防止类初始化。

假设失败会导致测试被忽略。

编辑:要与junit-ext@RunIf注释进行比较,其示例代码如下所示:

@Test
public void calculateTotalSalary() {
    assumeThat(Database.connect(), is(notNull()));
    //test code below.
}

更不用说以Database.connect()这种方式从方法中捕获和使用连接要容易得多。


1
@notnoop,那根本不是我的观察。他们被忽略。IDEA测试运行程序以这种方式报告它们,而查看JUnit源代码则表明它报告该测试被忽略。
Yishai

1
引用:“将来,这可能会改变,并且失败的假设可能会导致测试被忽略。” 实际上,我相信从4.5开始就发生了变化。当前的javadoc说:“默认的JUnit运行器将失败假设下的测试视为忽略。自定义运行器的行为可能有所不同。” github.com/KentBeck/junit/blob/…–
Yishai

4
带有Junit 4.8.1的Eclipse 3.6将错误的假设报告为通过测试。与ant 1.8.1相同。
fijiaaron 2010年

8
Eclipse报告失败的假设是通过错误:bugs.eclipse.org/bugs/show_bug.cgi?id=359944
Martin

1
@JeffStorey,那么您正在寻找一些东西。一种是@BeforeClass注释,您可以在此处使假设失败,从而跳过整个类。另一个是@ClassRule(用于细粒度控制,但在整个班级中,是一次)。
伊沙岛2012年

51

您应该结帐Junit-ext项目。它们具有RunIf执行条件测试的注释,例如:

@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
    //your code there
}

class DatabaseIsConnected implements Checker {
   public boolean satisify() {
        return Database.connect() != null;
   }
}

[摘自他们的教程的代码示例]


3
感谢您提供此答案-一种有趣的功能替代语法,尽管我将Assume直接进行介绍,以免引入其他依赖关系。
Andrzej Doyle

3
我个人更喜欢这种解决方案。如果您有许多应基于相同条件运行的测试,那将比在每个测试中都必须使用“假设”更为理想。同样,如果可以在类级别而不是方法级别上使用它,则将更加理想。
理查德

我更喜欢它,因为这有助于在运行时有条件地运行测试。它适合将要运行多个单元测试的地方,并且要求在特定的检查器上运行单元测试。我真的很惊讶地发现javen-ext在maven存储库中不可用。我们将如何在maven项目中利用这一点。
shambhu 2014年

4
像这样的注释@RunIf将应运行测试的条件与实际测试代码分开,我认为这很好。我不喜欢它需要特定的测试运行程序。因此,我编写了一个JUnit规则来确定地忽略测试。
吕迪格赫尔曼

2
在我们的本地存储库中安装了junit-ext jar(在此处找到code.google.com/p/junit-ext/downloads/…)并实现此@RunIf注释之后,什么都没有!它被完全忽略了,我认为原因可能是junit-ext似乎依赖于junit 4.5。由于弹簧测试,我们需要4.9+。所以...没关系。
Marc 2015年

7

在JUnit 4中,您可以选择的另一种选择是创建注释,以表示测试需要满足您的自定义条件,然后使用您自己的扩展默认运行器,并使用反射,将决定基于自定义条件。它可能看起来像这样:

public class CustomRunner extends BlockJUnit4ClassRunner {
    public CTRunner(Class<?> klass) throws initializationError {
        super(klass);
    }

    @Override
    protected boolean isIgnored(FrameworkMethod child) {
        if(shouldIgnore()) {
            return true;
        }
        return super.isIgnored(child);
    }

    private boolean shouldIgnore(class) {
        /* some custom criteria */
    }
}

虽然看起来不错,但如果使用JUnit4,则不能在当前版本中使用,因为JUnit4 BlockJUnit4ClassRunner不再提供该isIgnored方法。
戴夫

-2

快速说明:Assume.assumeTrue(condition)忽略其余步骤,但通过了测试。要使测试失败,请使用org.junit.Assert.fail()在条件语句中使用。像一样工作,Assume.assumeTrue()但测试失败。


5
正如在回答上面提到,一个失败的假设并没有导致测试通过,它返回一个单独的状态。一些跑步者可能会错误地报告此问题,好像通过了一样,但这是测试跑步者中的弱点/错误(并且默认的JUnit跑步者将测试显示为忽略)。至于最后一句话,考试不及格不是我想要做的。
Andrzej Doyle'8

哦好的。在我的情况下,测试以失败的假设通过,但我希望将其报告为失败(我正在检查Test Watcher中的异常)。强迫失败对我有帮助。
Tin Tin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.