Conditionally ignoring tests in JUnit 4
好的,所以@Ignore注释适用于标记不应运行测试用例。
但是,有时我想忽略基于运行时信息的测试。一个例子可能是我需要在具有一定数量内核的机器上运行并发测试。如果这个测试是在单处理器机器上运行的,我认为只是通过测试是不正确的(因为它还没有运行),并且当然不适合测试失败并打破构建。
所以我希望能够在运行时忽略测试,因为这似乎是正确的结果(因为测试框架将允许构建通过但记录测试未运行)。我很确定注释不会给我这种灵活性,并且怀疑我需要手动为相关类创建测试套件。但是,文档没有提到任何关于这一点并且通过API查看它也不清楚如何以编程方式完成(即,我如何以编程方式创建Test或类似的实例,该实例等同于< x0>注释?)。
如果有人在过去做过类似的事情,或者对如何做到这一点有一个明确的想法,我会很高兴听到它。
JUnit的方法是在运行时org.junit.Assume执行此操作。
1 2 3 4 5
| @Before
public void beforeMethod() {
org.junit.Assume.assumeTrue(someCondition());
// rest of setup.
} |
您可以在@Before方法或测试本身中执行此操作,但不能在@After方法中执行。如果您在测试中执行此操作,则@Before方法将运行。您也可以在@BeforeClass中执行此操作以防止类初始化。
假设失败导致测试被忽略。
编辑:要与junit-ext中的@RunIf注释进行比较,他们的示例代码如下所示:
1 2 3 4 5
| @Test
public void calculateTotalSalary() {
assumeThat(Database.connect(), is(notNull()));
//test code below.
} |
更不用说通过这种方式捕获和使用Database.connect()方法的连接要容易得多。
-
@notnoop,这根本不是我的观察。他们被忽略了。 IDEA测试运行器以这种方式报告它们,看看JUnit源代码显示它报告测试被忽略。
-
引用:"将来,这可能会改变,而失败的假设可能会导致测试被忽略。"它实际上发生了变化,我相信4.5。当前的javadoc说:"默认的JUnit运行器将失败假设的测试视为忽略。自定义运行器可能表现不同。" github.com/KentBeck/junit/blob/…
-
谢谢,这正是我正在寻找的。 Assume的语义听起来就像我在这里尝试的那样,所以即使跑步者不把它当作@Ignore,我相信它会被妥善处理。
-
带有Junit 4.8.1的Eclipse 3.6报告错误假设为通过测试。与ant 1.8.1相同。
-
@fijaaron,关于ANT,这是其XML格式的已知限制,并且由于许多工具依赖于这种格式,因此更改它是一个大问题,所以它不会发生这么快。关于eclipse,由于IDEA这样做,我不知道为什么eclipse还没有赶上。关于ANT功能,请参见:issues.apache.org/bugzilla/show_bug.cgi?id=43969
-
请注意,如果您以这种方式使用maven的surefire插件和JUnit,则需要使用surefire 2.7.2或更高版本来暂停测试,因为假设显示为Skipped而不是成功。
-
Eclipse报告失败的假设是传递错误:bugs.eclipse.org/bugs/show_bug.cgi?id = 359944
-
如果你有一个After方法,看起来After方法仍然运行,但它看起来不像Assume可以在After方法中使用。反正有没有阻止前后方法运行?
-
@JeffStorey,after方法只在假设在方法本身而不在之前运行时运行。这是有道理的 - 如果有一个之前,将有一个后。您可以使用TestRule获得更精细的控制。 kentbeck.github.com/junit/javadoc/latest/org/junit/rules/…
-
@Yishai,我设置了一个简单的测试,我在前面的方法中放了Assume.assumeTrue(false),但是after方法仍然运行。听起来这与你的期望相反......
-
@JeffStorey,我也设置了一个测试,它按照我的描述工作,或者至少我认为它确实如此。我再试一次,你是对的。我想TestRule是要走的路。
-
@Yishai,谢谢。我不确定TestRule是否适用于这种情况。如果假设为假而没有注释每个方法,试图找到一种基本上忽略整个测试类的方法。如果需要处理一些注释,我总是可以编写自定义运行器。
-
@JeffStorey,那么你正在寻找一些东西。一个是@BeforeClass注释,在那里你可以让你的假设失败,这将跳过整个班级。另一个是@ClassRule(对于细粒度控制,但在整个类中,一次)。
-
谢谢,我从未真正想过在beforeClass方法中使用Assume。我会试一试。我也将研究ClassRule。谢谢。
-
太棒了!我将使用这种方法将我的烟雾测试与eclipse和maven分开。甜。
-
这不是正确的答案。这不会导致测试被忽略或"通过"。它仍然运行测试方法的代码。正确的方法是使用@ KyleShrader的建议
-
在我的情况下,我去Assume方式。有时条件因测试而异,我可以使用类型A的输入运行测试A并使用类型B的输入运行testB;然后@Before不是要走的路,因为它在每次测试之前执行,因此条件必须相同。
-
注:即使失败的假设是在@Before方法中,@After方法仍将运行。
你应该结帐Junit-ext项目。它们具有执行条件测试的RunIf注释,例如:
1 2 3 4 5 6 7 8 9 10 11
| @Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
//your code there
}
class DatabaseIsConnected implements Checker {
public boolean satisify() {
return Database.connect() != null;
}
} |
[代码示例取自他们的教程]
-
感谢这个答案 - 这个功能的一个有趣的替代语法,虽然我将直接使用Assume以便不引入另一个依赖项。
-
我个人更喜欢这个解决方案如果您有许多应该基于相同条件运行的测试,那么这比在每个测试中使用Assume要理想得多。此外,如果这可以在类级别而不是方法级别上使用,那么它将更加理想。
-
在Maven Central上没有junit-ext :-(
-
我更喜欢它,'因为这有助于在运行时有条件地运行测试。它适用于要运行多个单元测试的地方,并且要求在特定检查器上运行单元测试。我真的很惊讶看到junit-ext在maven资源库中不可用。我们如何在maven项目中获得这个效果。
-
像@RunIf这样的注释将测试运行时的条件与实际测试代码分开,我认为这是好的。我不喜欢的是它需要一个特定的测试运行器。因此,我写了一个JUnit规则来条件地忽略测试。
-
在我们的本地存储库中安装junit-ext jar(在这里找到code.google.com/p/junit-ext/downloads/…)并实现这个@RunIf注释...没有!它完全被忽略了,我认为原因可能是junit-ext似乎依赖于junit 4.5。由于弹簧测试,我们需要4.9+。所以......别介意。
-
Checker ???的命名空间是什么?
在JUnit 4中,另一个选项可能是创建注释以表示测试需要满足您的自定义条件,然后使用您自己的反射扩展默认运行器,根据自定义条件做出决策。它可能看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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 */
}
} |
快速说明:Assume.assumeTrue(condition)忽略其余步骤但通过测试。
要使测试失败,请在条件语句中使用org.junit.Assert.fail()。与Assume.assumeTrue()相同,但未通过测试。
-
如上面的答案所述,失败的假设不会导致测试通过,它会返回一个单独的状态。一些跑步者可能错误地报告这个好像是传球,但这是测试跑步者的弱点/错误(默认的JUnit跑者将测试视为忽略)。至于你的最后一句话,未通过测试特别不是我想要做的。
-
哦好的。在我的案例中,测试通过了失败的假设,但我希望它们被报告为失败(我正在检查Test Watcher的异常)。强迫失败帮助了我。