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

mel*_*ort 3 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()
Run Code Online (Sandbox Code Playgroud)

对于一种方法有这么多测试方法似乎很草率.我想只有一个测试方法,并放置了大量的基本测试用例(即4!== 24,3!== 6,5!== 120,依此类推),但是unittest不允许你去做.

在这种情况下构建测试文件的最佳方法是什么?

在此先感谢您的帮助.

int*_*jay 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)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此解决方案提供了一个测试,一旦第一个案例失败就会失败,因此您将丢失有关后续案例是通过还是失败的任何信息.这可能是您想要的行为,也可能不是. (2认同)

rbp*_*rbp 5

我会说你做这件事的方式一般都很好(但请继续阅读).

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

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

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

def test_fact_5(self):
    self.assertFalse(1==fact(5))
Run Code Online (Sandbox Code Playgroud)

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

def test_fact_6(self):
    self.assertRaises(RuntimeError, fact, -1)
Run Code Online (Sandbox Code Playgroud)

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