(二) 限时测试
在前面的例子中,我为squareRoot()方法编写了一个测试用例。记住,在这个方法中存在一个错误-能够导致它无限循环。如果没有结果的话,我想 让这个测试在1秒钟后退出。这一功能正是timeout参数所要实现的。@Test注解的第二个可选参数(第一个参数是必需的)可以使一个测试失败,如果 该测试花费比一个预先确定的时限(毫秒)还长的时间的话。当我运行该测试时,我得到如下的运行结果:
There was 1 failure:
1) squareRoot(JUnit 4.AdvancedTest)
java.lang.Exception: test timed out after 1000 milliseconds
at org.junit.internal.runners.TestMethodRunner.runWithTimeout(TestMethodRunner.java:68)
at org.junit.internal.runners.TestMethodRunner.运行(TestMethodRunner.java:43)
FAILURES!!!
Tests run: 4, Failures: 1
三) 参数化测试
在列表1中,我测试了squareRoot(它是square方法而不是squareRoot方法)-通过创建若干测试方法(square2, square4,square5),这些方法都完成相同的事情(通过被一些变量参数化实现)。其实,现在这里的复制/粘贴技术可以通过使用一个参数化测试 用例加以优化(列表2)。
在列表2(见本文相应下载源码)中的测试用例使用了两个新的注解。当一个类被使用@RunWith注释时, JUnit将调用被参考的类来运行该测试而不是使用缺省的运行机。为了使用一个参数化测试用例,你需要使用运行机 org.junit.runners.Parameterized。为了确定使用哪个参数,该测试用例需要一个公共静态方法(在此是data(),但是名 字似乎无关),该方法返回一个Collection,并且被使用@参数加以注解。你还需要一个使用这些参数的公共构造函数。
当运行这个类,该输出是:
java org.junit.runner.JUnitCore JUnit 4.SquareTest
JUnit version 4.1
.......E
There was 1 failure:
1) square[6](JUnit 4.SquareTest)
java.lang.AssertionError: expected:<48> but was:<49>
at org.junit.Assert.fail(Assert.java:69)
FAILURES!!!
Tests run: 7, Failures: 1
在此,共执行了7个测试,好象编写了7个单独的square方法。注意,在我们的测试中出现了一个失败,因为7的平方是49,而不是48。
(四) 测试集
为了在JUnit 3.8的一个测试集中运行若干测试类,你必须在你的类中添加一个suite()方法。而在JUnit 4中,你可以使用注解来代之。为了运行CalculatorTest和SquareTest,你需要使用@RunWith和@Suite注解编写一个空 类。
package JUnit 4;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
CalculatorTest.class,
SquareTest.class
})
public class AllCalculatorTests {}
在此,@RunWith注解告诉JUnit它使用org.junit.runner.Suite。这个运行机允许你手工地构建一个包含测试(可能来自许 多类)的测试集。这些类的名称都被定义在@Suite.SuiteClass中。当你运行这个类时,它将运行CalculatorTest和 SquareTest。其输出是:
java -ea org.junit.runner.JUnitCore JUnit 4.AllCalculatorTests
JUnit version 4.1
...E.EI.......E
There were 3 failures:
1) subtract(JUnit 4.CalculatorTest)
java.lang.AssertionError: expected:<9> but was:<8>
at org.junit.Assert.fail(Assert.java:69)
2) divide(JUnit 4.CalculatorTest)
java.lang.AssertionError
at JUnit 4.CalculatorTest.divide(CalculatorTest.java:40)
3) square[6](JUnit 4.SquareTest)
java.lang.AssertionError: expected:<48> but was:<49>
at org.junit.Assert.fail(Assert.java:69)
FAILURES!!!
Tests run: 11, Failures: 3
(五) 测试运行机
在JUnit 4中,广泛地使用测试运行机。如果没有指定@RunWith,那么你的类仍然会使用一个默认运行机 (org.junit.internal.runners.TestClassRunner)执行。注意,最初的Calculator类中并没有显式地声 明一个测试运行机;因此,它使用的是默认运行机。一个包含一个带有@Test的方法的类都隐含地拥有一个@RunWith。事实上,你可以把下列代码添加 到Calculator类上,而且其输出结果会完全一样。
import org.junit.internal.runners.TestClassRunner;
import org.junit.runner.RunWith;
@RunWith(TestClassRunner.class)
public class CalculatorTest {
...
}
在@Parameterized和@Suite的情况下,我需要一个特定的运行机来执行我的测试用例。这就是为什么我显式地注解了它们。