TestCase类在整个JUnit框架中处于核心的地位。你可以在junit.framework包中发现TestCase这个类。在JUnit开发人员当中,甚至是在一些高级的程序员当中,都有一个疑惑,那就是测试用例(test case)和TestCase类之间的关系。事实上,这是个命名冲突问题。“测试用例”(test case)这个术语通常指的是单个的测试,通过编码来校验某个特定的行为。那么,将多个测试用例都收集到一个类中,这个类是TestCase的子类,而且每一个测试用例都被实现为TestCase类中的一个方法,这的确有些奇怪。既然这个类包含了多个测试用例(test case),那为什么把它叫成“TestCase”而不是叫做“测试集”之类的名字呢?
在这里我们给出最好的解释:虽然在编写测试的时候,你需要创建一个“TestCase”的子类,并把每个测试用例都实现为这个新类的方法;但是在运行的时候,每个测试用例都会被当作TestClass子类的一个实例来运行。使用面向对象的术语来说,每个测试用例都是一个TestCase的对象,因此,这个名字还是合适的。不过,一个TestCase包含了很多的测试,这的确引起了术语的疑惑。这也是为什么我们如此小心地区分一个测试用例(test case)和TestCase这个类:前者是单个的测试,而后者则包含了多个测试,每个测试都用不同的方法来实现。为了更清楚的区分这两个概念,我们不会再(尽量做到不再)使用测试用例(test case)这个术语。要么就用测试(test)这个词,要么就用”TestCase”这个类名。在这本书的后面,我们还会把这个“TestCase”类称为“固定器(fixture)”。不再过多地解释这个描述,我们以后再谈这个“固定器”。现在我们把固定器想象成将多个测试自然组合到一起的方式,然后JUnit可以统一执行这些测试。“TestCase”类提供了一个默认的方式来确定哪些方法属于测试,但是你可以以自己的方式来组织测试。在第4章中,描述了多种不同的方法从你的测试中来创建测试套件。
在JUnit框架结构中,TestCase类扩展了一个叫做Assert的工具类。这个Assert类提供了很多方法来让你对当前的对象的状态做“断言”。正因为TestCase扩展了Assert,因此你可以不需要引用外部的类就能编写自己的断言了。在JUnit中,基本的断言方法如表1.2所描述。
表1.2 JUnit中的Assert类提供了多种做断言的方法
方法 | 它实做什么的 |
assertTrue(boolean condition) | 如果condition为false则失败;否则通过测试 |
assertEquals(Object expected, Object actual) | 根据equals()方法,如果expected和actual不相等则失败;否则通过测试 |
assertEquals(int expected, int actual) | 根据==操作符,如果expected和actual不相等则失败;否则通过测试。对每一个原始类型:int、float、double、char、byte、long、short和boolean,这个方法都会都一个函数的重载。(参见assertEquals() 的注释) |
assertSame(Object expected, Object actual) | 如果expected和actual引用不同的内存对象则失败;如果它们引用相同的内存对象则通过测试。两个对象可能并不是相同的,但是它们可能通过equals()方法仍然可以是相等的 |
assertNull(Object object) | 如果对象为null则通过测试,反之看作失败 |
JUnit还提供了正好和表中列出的逻辑相反的其他断言操作:assertFalse()、assertNotSame()和assertNotNull();但是没有assertNotEquals(),如果想有这个方法,需要更多的有关定制JUnit的知识,请参见第3章。
注意:有两个assertEquals()的重载函数稍有不同。用来比较double和float的版本需要第三个参数:“精确程度”。这个精确程度确定了两个浮点值需要有多接近才能被认为它们是相等的。因为浮点运算并不是完全精确的,你可能会决定“这两个值如果相差不超过0.0001,那么它们就足够相近了”,用函数的方式来表达就是assertEquals(expectedDouble, actualDouble, 0.0001d)。