好的,所以 @Ignore
注释非常适合标记不应运行测试用例。
但是,有时我想忽略基于运行时信息的测试。例如,如果我有一个并发测试需要在具有一定数量内核的机器上运行。如果这个测试是在单处理器机器上运行的,我认为只通过测试是不正确的(因为它还没有运行),而且测试失败并破坏构建肯定是不对的.
所以我希望能够在运行时忽略测试,因为这似乎是正确的结果(因为测试框架将允许构建通过但记录测试未运行)。我相当确定注释不会给我这种灵活性,并且怀疑我需要为相关类手动创建测试套件。但是,文档没有提及任何关于此的内容,并且通过 API 查看它也不清楚这将如何以编程方式完成(即,我如何以编程方式创建 Test
的实例或类似于由@Ignore
注释?)。
如果有人过去做过类似的事情,或者对我还能如何解决这个问题有一个好主意,我会很高兴听到这个消息。
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()
方法捕获和使用连接要容易得多。
您应该签出 Junit-ext
项目。它们具有执行条件测试的 RunIf
注释,例如:
@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
//your code there
}
class DatabaseIsConnected implements Checker {
public boolean satisify() {
return Database.connect() != null;
}
}
[取自他们的教程的代码示例]
Assume
以避免引入另一个依赖项。
@RunIf
这样的注释将测试应该运行的条件与实际测试代码分开,我认为这很好。我不喜欢的是它需要一个特定的测试运行器。因此我写了一个 JUnit rule 来条件性地忽略测试。
在 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 */
}
}
BlockJUnit4ClassRunner
不再提供 isIgnored
方法。
除了@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 ...
}
}
快速说明:Assume.assumeTrue(condition)
忽略其余步骤但通过了测试。要使测试失败,请在条件语句中使用 org.junit.Assert.fail()
。与 Assume.assumeTrue()
一样工作,但未通过测试。
@BeforeClass
注释,您可以在那里让您的假设失败,这将跳过整个课程。另一个是@ClassRule
(用于细粒度控制,但在整个班级,一次)。