多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 13.4. 正面测试 (Testing for success) 单元测试的基础是构建独立的测试用例 (test case)。一个测试用例只回答一个关于被测试代码的问题。 一个测试用例应该做到: * 完全独立运行,不需要人工输入。单元测试应该是自动的。 * 可以自己判断被测试函数是通过还是失败,不需要人工干预结果。 * 独立运行,可以与其他测试用例隔离 (尽管它们可能测试着同一个函数)。每个测试用例是一个孤岛。 基于如上原则,让我们构建第一个测试用例。应符合如下[要求](index.html#roman.requirements): 1. `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) ``` | | | | --- | --- | | \[1\] | 编写测试用例的第一步就是继承 `unittest` 模块中的 `TestCase` 类,它提供了很多可以用在你的测试用例中来测试特定情况的有用方法。 | | \[2\] | 这是我手工转换的一个 integer/numeral 对列表。它包含了最小的十个数、最大的数、每个单字符罗马数字对应的数,以及其他随机挑选的有效数样本。单元测试的关键不在于所有可能的输入,而是一个有代表性的样本。 | | \[3\] | 每个独立测试本身都是一个方法,既不需要参数也不返回任何值。如果该方法正常退出没有引发异常,测试被认为通过;如果测试引发异常,测试被认为失败。 | | \[4\] | 这里你真正调用了 `toRoman` 函数。(当然,函数还没有编写,但一旦被编写,这里便是调用之处。) 注意你在这里为 `toRoman` 函数定义了 API :它必须接受整数 (待转换的数) 并返回一个字符串 (对应的罗马数字表示),如果 API 不是这样,测试将失败。 | | \[5\] | 同样值得注意,你在调用 `toRoman` 时没有试图捕捉任何可能发生的异常。这正是我们所希望的。以有效输入调用 `toRoman` 不会引发任何异常,而你看到的这些输入都是有效的。如果 `toRoman` 引发了异常,则测试失败。 | | \[6\] | 假设 `toRoman` 函数被正确编写,正确调用,运行成功并返回一个值,最后一步便是检查这个返回值_正确_ 与否。这是一个常见的问题,`TestCase` 类提供了一个方法:`assertEqual`,来测试两个值是否相等。如果 `toRoman` 返回的结果 (`value`) 不等于我们预期的值 (`numeral`),`assertEqual` 将会引发一个异常,测试也就此失败。如果两个值相等,`assertEqual` 什么也不做。如果每个从 `toRoman` 返回的值都等于预期值,`assertEqual` 便不会引发异常,于是 `testToRomanKnownValues` 最终正常退出,这意味着 `toRoman` 通过了该测试。 |