在Python中提供测试数据

12 投票
5 回答
16373 浏览
提问于 2025-04-16 19:34

我该如何对很多不同的数据进行相同的测试呢?

我希望能收到所有失败的报告。

举个例子:

def isEven(number):
    return True # Quite buggy implementation

data = [
    (2, True),
    (3, False),
    (4, True),
    (5, False),
]

class MyTest:
   def evenTest(self, num, expected):
       self.assertEquals(expected, isEven(num))

我找到的解决方案只会在第一次失败时抛出错误:在Python单元测试中使用PHPUnit风格的数据提供者

我该如何运行一个测试,以便能收到所有失败的报告呢?

5 个回答

8

一种解决方法是为data中的每个条目创建不同的测试用例实例:

class MyTest(unittest.TestCase):
    def __init__(self, num, expected):
        unittest.TestCase.__init__(self, "evenTest")
        self.num = num
        self.expected = expected
    def evenTest(self):
        self.assertEqual(self.expected, isEven(self.num))

为了让unittest知道如何构建这些测试用例,你需要在你的模块中添加一个load_tests()函数:

def load_tests(loader, tests, pattern):
    return unittest.TestSuite(MyTest(num, expected)
                              for num, expected in data)
12

如果你在使用 pytest,你可以这样做:

import pytest

def is_even(number):
    return True # Wuite buggy implementation

@pytest.mark.parametrize("number, expected", [
    (2, True),
    (3, False),
    (4, True),
    (5, False)
])
def test_is_even(number, expected):
    assert is_even(number) == expected

你会得到类似下面的结果(简化版):

/tmp/test_it.py:13: AssertionError
=========== 2 failed, 2 passed in 0.01 seconds ====================
8

你应该使用 py.test。我觉得unittest模块是从JUnit抄来的。无论如何,你可以这样来解决问题:

import unittest

data = [
    (2, True),
    (3, False),
    (4, True),
    (5, False)]

# This should be imported from a separate module.
def isEven(number):
    return True # Quite buggy implementation

def create_test_func(num, expected):
    def _test_func(self):
        self.assertEqual(expected, isEven(num))
    return _test_func

class TestIsEven(unittest.TestCase):

    pass

# pyunit isn't Pythonic enough. Use py.test instead
# till then we rely on such hackery
import new
for i, (num, expected) in enumerate(data):
    setattr(TestIsEven, 'test_data_%d'%i, create_test_func(num, expected))

if __name__ == "__main__":
    unittest.main()

然后输出结果是:

.F.F
======================================================================
FAIL: test_data_1 (__main__.TestIsEven)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "untitled-1.py", line 15, in _test_func
    self.assertEqual(expected, isEven(num))
AssertionError: False != True

======================================================================
FAIL: test_data_3 (__main__.TestIsEven)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "untitled-1.py", line 15, in _test_func
    self.assertEqual(expected, isEven(num))
AssertionError: False != True

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures=2)

通过这种方法,你还可以添加一些额外的功能,比如在出错时打印调试信息等等。

撰写回答