使用unittest的Python中许多测试用例的正确结构

时间:2010-06-01 19:30:24

标签: python unit-testing

我正在查看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 个答案:

答案 0 :(得分:6)

您可以将断言置于循环中:

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)

答案 1 :(得分:5)

我会说你这样做的方式通常很好(但请继续阅读)。

正如interjay建议的那样,你可以做一个循环(顺便说一下,它只算作一个测试,因为unittest模块计算函数的数量,而不是断言的数量)。但我认为你不会穷尽地尝试测试每个号码,甚至是非常大的间隔内的所有数字。因此循环不会为您节省太多,特别是在测试中,您应该以明确为目标。

话虽如此,您应该测试少量后续数字(例如,1到5),然后尝试了解角落案例和失败点的可能性。比如说,测试10,100,1000(即变化的数量级),负数,零等等。

顺便说一下,请注意你最近的两次测试。第一个并不意味着什么。事实(5)不同于很多数字(实际上是无限数字)。测试正确的情况,测试不正确的情况是没有效果的。

def test_fact_5(self):
    self.assertFalse(1==fact(5))

第二个名字很糟糕:“test_fact_6”让我觉得你在测试事实(6)。您应将其命名为“test_fact_minus_one”,或至少“test_fact_negative_number”。

def test_fact_6(self):
    self.assertRaises(RuntimeError, fact, -1)

测试命名非常重要,无论是在调试错误时还是作为文档返回测试时。

答案 2 :(得分:0)

您已经说过要调查unittest,但考虑使用nose测试 - 它们允许您以编程方式生成独立的测试用例。

How to generate dynamic (parametrized) unit tests in python?(回答)