使用unittest在Python中处理多个测试用例的合适结构
我在研究 unittest
这个包,但不太确定在为同一个方法写很多测试用例时,应该怎么组织我的测试用例。假设我有一个 fact
函数,它用来计算一个数字的阶乘;这样写的测试文件可以吗?
import unittest
class functions_tester(unittest.TestCase):
def test_fact_1(self):
self.assertEqual(1, fact(1))
def test_fact_2(self):
self.assertEqual(2, fact(2))
def test_fact_3(self):
self.assertEqual(6, fact(3))
def test_fact_4(self):
self.assertEqual(24, fact(4))
def test_fact_5(self):
self.assertFalse(1==fact(5))
def test_fact_6(self):
self.assertRaises(RuntimeError, fact, -1)
#fact(-1)
if __name__ == "__main__":
unittest.main()
我觉得为一个方法写这么多测试方法有点乱。我想只写一个测试方法,然后把很多基本的测试用例放进去(比如 4! == 24,3! == 6,5! == 120,等等),但是 unittest
不允许这样做。
在这种情况下,组织测试文件的最佳方式是什么呢?
提前谢谢你的帮助。
3 个回答
你提到你在研究 unittest
,但不妨考虑使用 nose
测试。因为 nose
可以让你通过编程的方式生成独立的测试案例。
我觉得你现在的做法 大体上 是可以的(不过接着往下看)。
你可以像interjay建议的那样,使用循环(顺便说一下,这样只算一个测试,因为unittest模块是根据函数的数量来计算的,而不是根据断言的数量)。不过我猜你不会试着去测试 每一个 数字,甚至不会测试一个非常大的范围内的所有数字。所以用循环其实帮不了你太多,特别是在测试的时候,你应该尽量做到明确。
话虽如此,你应该测试一小部分连续的数字(比如说,1到5),然后尝试找出可能的边界情况和失败点。比如,测试10、100、1000(也就是改变数量级),负数,零等等。
顺便提一下,注意你最后两个测试。第一个测试的意义不大。fact(5)和很多数字是不同的(实际上是无穷多个数字)。测试正确的情况,测试错误的情况并没有什么帮助。
def test_fact_5(self):
self.assertFalse(1==fact(5))
第二个测试的名字起得不好:“test_fact_6”让我以为你在测试fact(6)。你应该把它命名为“test_fact_minus_one”,或者至少是“test_fact_negative_number”。
def test_fact_6(self):
self.assertRaises(RuntimeError, fact, -1)
测试的命名非常重要,无论是在调试错误的时候,还是在你回头查看测试作为文档的时候。
你可以把这些检查放在一个循环里:
def test_fact(self):
tests = [(1,1), (2,2), (3,6), (4,24), (5,120)]
for n,f in tests:
self.assertEqual(fact(n), f)