让我们据此为第一个需求建立一个测试用例:
to_roman()
方法应该返回代表1
-3999
的罗马数字。这些代码功效如何并不那么显而易见。它定义了一个没有
__init__
方法的类。而该类当然有其它方法,但是这些方法都不会被调用。在整个脚本中,有一个__main__ 块,但它并不引用该类及它的方法。但我承诺,它做别的事情了。import roman1 import unittest class KnownValues(unittest.TestCase): ① known_values = ( (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 test_to_roman_known_values(self): ③ '''to_roman should give known result with known input''' for integer, numeral in self.known_values: result = roman1.to_roman(integer) ④ self.assertEqual(numeral, result) ⑤ if __name__ == '__main__': unittest.main()
编写一个失败的测试,然后进行编码直到该测试通过。
① 为了编写测试用例,首先使该测试用例类成为 unittest
模块的TestCase
类的子类。TestCase 提供了很多你可以用于测试特定条件的测试用例的有用的方法。② 这是一张我手工核实过的整型数字-罗马数字对的列表。它包括最小的十个数字、最大数字、每一个有唯一一个字符串格式的罗马数字的数字以及一个有其它有效数字产生的随机数。你没有必要测试每一个可能的输入,而需要测试所有明显的边界用例。 ③ 每一个独立的测试都有它自己的不含参数及没有返回值的方法。如果方法不抛出异常而正常退出则认为测试通过;否则,测试失败。 ④ 这里调用了真实的 to_roman()
方法. (当然,该方法还没编写;但一旦该方法被实现,这就是调用它的行号)。注意,现在你已经为to_roman()
方法定义了 接口:它必须包含一个整型(被转换的数字)及返回一个字符串(罗马数字的表示形式)。如果 接口 实现与这些定义不一致,那么测试就会被视为失败。同样,当你调用to_roman()
时,不要捕获任何异常。这些都是unittest 故意设计的。当你以有效的输入调用to_roman()
时它不会抛出异常。如果to_roman()
抛出了异常,则测试被视为失败。⑤ 假设 to_roman()
方法已经被正确定义,正确调用,成功实现以及返回了一个值,那么最后一步就是去检查它的返回值是否 right 。这是测试中一个普遍的问题。TestCase
类提供了一个方法assertEqual
来检查两个值是否相等。如果to_roman()
(result) 的返回值跟已知的期望值g (numeral)不一致,则抛出异常,并且测试失败。如果两值相等,assertEqual
不会做任何事情。如果to_roman()
的所有返回值均与已知的期望值一致,则assertEqual
不会抛出任何异常,于是,test_to_roman_known_values
最终会会正常退出,这就意味着to_roman()
通过此次测试。一旦你有了测试用例,你就可以开始编写
to_roman()
方法。首先,你应该用一个空方法作为存根,同时确认该测试失败。因为如果在编写任何代码之前测试已经通过,那么你的测试对你的代码是完全不会有效果的!单元测试就像跳舞:测试先行,编码跟随。编写一个失败的测试,然后进行编码直到该测试通过。