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

好,所以@Ignore注释用于标记不应该运行测试用例。

然而,有时我想忽略基于运行时信息的测试。例如,如果我有一个并发测试,需要在具有一定数量内核的机器上运行。如果这个测试是在一台单处理器机器上运行的,我认为仅仅通过测试是不正确的(因为它还没有运行),并且失败测试并破坏构建当然也不正确。

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

如果有人在过去做过类似的事情,或者有一个关于我如何做这件事的好主意,我很乐意听听。

132262 次浏览

你应该签出Junit-ext项目。它们有RunIf注释,执行条件测试,例如:

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


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

[摘自教程的代码示例]

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()方法捕获和使用连接要容易得多。

快速提示:Assume.assumeTrue(condition)忽略其余步骤,但通过了测试。 要使测试失败,在条件语句中使用org.junit.Assert.fail()。工作方式与Assume.assumeTrue()相同,但测试失败

在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 */
}
}
< p > 另外@tkruse和@Yishai的答案:
我这样做是为了有条件地跳过测试方法,特别是Parameterized测试,如果一个测试方法只应该对一些测试数据记录运行
public class MyTest {
// get current test method
@Rule public TestName testName = new TestName();
    

@Before
public void setUp() {
org.junit.Assume.assumeTrue(new Function<String, Boolean>() {
@Override
public Boolean apply(String testMethod) {
if (testMethod.startsWith("testMyMethod")) {
return <some condition>;
}
return true;
}
}.apply(testName.getMethodName()));
        

... continue setup ...
}
}