6.3. 成功目的测试

单元测试最基础的部分是构建独立的单试用例。一个测试用例回答关于正在测试代码的一个问题。

一个测试用例应该能够…

知道这个后,让我们创建我们第一个测试用例。我们有下面的需求

  1. toRoman 应该返回所有从 13999 的数字的罗马数字表示。

例 6.2. testToRomanKnownValues


class KnownValues(unittest.TestCase):                           1
    knownValues = ( (1, 'I'),
                    (2, 'II'),
                    (3, 'III'),
                    (4, 'IV'),
                    (5, 'V'),
                    (6, 'VI'),
                    (7, 'VII'),
                    (8, 'VIII'),
                    (9, 'IX'),
                    (10, 'X'),
                    (50, 'L'),
                    (100, 'C'),
                    (500, 'D'),
                    (1000, 'M'),
                    (31, 'XXXI'),
                    (148, 'CXLVIII'),
                    (294, 'CCXCIV'),
                    (312, 'CCCXII'),
                    (421, 'CDXXI'),
                    (528, 'DXXVIII'),
                    (621, 'DCXXI'),
                    (782, 'DCCLXXXII'),
                    (870, 'DCCCLXX'),
                    (941, 'CMXLI'),
                    (1043, 'MXLIII'),
                    (1110, 'MCX'),
                    (1226, 'MCCXXVI'),
                    (1301, 'MCCCI'),
                    (1485, 'MCDLXXXV'),
                    (1509, 'MDIX'),
                    (1607, 'MDCVII'),
                    (1754, 'MDCCLIV'),
                    (1832, 'MDCCCXXXII'),
                    (1993, 'MCMXCIII'),
                    (2074, 'MMLXXIV'),
                    (2152, 'MMCLII'),
                    (2212, 'MMCCXII'),
                    (2343, 'MMCCCXLIII'),
                    (2499, 'MMCDXCIX'),
                    (2574, 'MMDLXXIV'),
                    (2646, 'MMDCXLVI'),
                    (2723, 'MMDCCXXIII'),
                    (2892, 'MMDCCCXCII'),
                    (2975, 'MMCMLXXV'),
                    (3051, 'MMMLI'),
                    (3185, 'MMMCLXXXV'),
                    (3250, 'MMMCCL'),
                    (3313, 'MMMCCCXIII'),
                    (3408, 'MMMCDVIII'),
                    (3501, 'MMMDI'),
                    (3610, 'MMMDCX'),
                    (3743, 'MMMDCCXLIII'),
                    (3844, 'MMMDCCCXLIV'),
                    (3888, 'MMMDCCCLXXXVIII'),
                    (3940, 'MMMCMXL'),
                    (3999, 'MMMCMXCIX'))                        2

    def testToRomanKnownValues(self):                           3
        """toRoman should give known result with known input"""
        for integer, numeral in self.knownValues:              
            result = roman.toRoman(integer)                     4 5
            self.assertEqual(numeral, result)                   6
1

为了编写一个测试用例,首先要将 unittest 模块中的 TestCase 类子类化。这个类提供了许多有用的函数,你可以在你的测试用例中使用它们,对特殊条件进行测试。

2

这是一个我手工校验过的整数/罗马数字对的列表。它包括了最小的 10 个数字,最大的数字,所有可以转换为单个罗马数字字符的数字,和其它有效数字的随机采样。单元测试的要点不是对每个可能的输入进行测试,而是对有代表性的例子进行测试。

3

每个独立的测试都有它自已的方法,它不能接收参数也不参返回值。如果这个方法正常退出,没有引发异常,测试被认为通过;如果方法引发异常,测试被认为失败。

4

在这儿我们调用实际的 toRoman 函数。(嗯,这个函数还没写出来呢,但一旦写出来,这就是我们将调用的那行代码。)请注意我们现在已经定义了 toRoman 函数API:它必须接收一个整数(将被转换的整数),并返回一个字符串(罗马数字表示)。如果API与这里的不同,这个测试被认为失败。

5

还要注意在调用 toRoman 时,我们没有捕捉任何引常。这是故意的。当我们用有效的输入调用它,并且这些输入值都是有效值时,toRoman 不应该引发一个异常。如果 toRoman 引发一个异常,这个测试被认为失败。

6

假设这个 toRoman 函数正确定义,正确调用,成功完成,并返回一个值,最后一步就是检查是否它返回了正确值。这是一个常见的问题,则 TestCase 类提供了一个方法,assertEqual,检查两个值是否相等。如果从 toRoman (result) 返回的值与我们期望的值 (numeral) 不匹配,assertEqual 将引发一个异常,并测试将失败。如果两个值相等,assertEqual 将什么都不做。如果每个从 toRoman 返回的值都与我们所期望的值相匹配,assertEqual 决不会引发异常,所以 testToRomanKnownValues 最终会正常退出,这就意味着 toRoman 通过了这个测试。