13.4. 正面测试(Testing for success)
优质
小牛编辑
131浏览
2023-12-01
13.4. 正面测试(Testing for success)
单元测试的基础是构建独立的测试用例(test case)。 一个测试用例只回答一个关于被测试代码的问题。
一个测试用例应该做到:
- 完全独立运行,不需要人工输入。单元测试应该是自动的。
- 可以自己判断被测试函数是通过还是失败,不需要人工干预结果。
- 隔离运行,可以与其他测试用例隔离(尽管他们可能测试着同一个函数)。每个测试用例是一个孤岛。
基于如上原则,让我们构建第一个测试用例。应符合如下 要求:
- toRoman 应该为所有 1 到 3999 的整数返回罗马数字表示。
例 13.2. testToRomanKnownValues
class KnownValues(unittest.TestCase): 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')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman.toRoman(integer) self.assertEqual(numeral, result)
编写测试用例首先需要写一个类来继承 unittest 模块中的 TestCase 类,TestCase 类提供了很多可以用在你的测试用例中来测试特定情况的有用方法。 | |
这是我手工转换的一个 integer/numeral 对列表。 它包含了最小的十个数,最大数,每个单字符罗马数字对应的数,以及其他随即挑选的有效数样本。单元测试的关键不在于所有可能的输入,而是一个有代表性的样本。 | |
每个独立测试都是其自己的方法,既不需要参数也不返回任何值。如果该方法正常退出没有引发异常,测试被认为通过;如果测试引发异常,测试被认为失败。 | |
这里你真正调用了 toRoman 函数。(当然,函数还没有编写,但一旦被编写,这里便是调用之处) 注意你在这里为 toRoman 函数定义了 API :它必须接受整数(待转换的数)并返回一个字符串(对应的罗马数字表示), 如果 API 不是这样,测试将失败。 | |
" 同样值得注意,你在调用 toRoman 时没有试图捕捉任何可能发生的异常。这正是我们所希望的。以有效输入调用 toRoman 不会引发任何异常,因此这些输入都是有效的。如果 toRoman 引发了异常,则测试被认为失败(输入是无效的)。 | |
假设 toRoman 函数被正确编写,正确调用,运行成功并返回一个值,最后一步便是检查这个返回值正确与否。这是一个常见的问题, TestCase 类提供了一个方法: assertEqual 来测试两个值是否相等。如果 toRoman 返回的结果 (value) 不等于我们预期的值 (numeral), assertEqual 将会引发一个异常,测试也就此失败。如果两个值相等,assertEqual 什么也不做。如果每个从 toRoman 返回的值都等于预期值 assertEqual 便不会引发异常, 于是 testToRomanKnownValues 最终正常退出,这意味着 toRoman 通过了该测试。 |