2011-06-14 59 views
9

如何针对大量不同的数据运行相同的测试?我想要报告全部失败。在python中提供测试数据

例如:

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)) 

我已经找到解决方案,提出了只有第一次失败的错误: http://melp.nl/2011/02/phpunit-style-dataprovider-in-python-unit-test/

如何运行测试报告所有的失败?

回答

5

您应该使用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 enought 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) 

使用这种方法你可以添加更多的细节,如打印调试失败信息等

+0

+1,关于'我认为unittest模块被盲目地从junit复制过来,它是不是唯一一个从java-like复制过来的:) – mouad 2011-06-15 07:13:50

-1
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 


class TestIsEven(unittest.TestCase): 
    def test_is_even(self): 
     for num, expected in data: 
      self.assertEqual(expected, isEven(num)) 
+0

这就提出了第一个错误 - 再次阅读问题的结束。 – 2011-06-14 21:31:33

7

一种解决方案是让每个条目不同的测试案例的实例在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) 
3

你是在找这样的事:

import unittest 


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


class TestCase(unittest.TestCase): 
    def setUp(self): 
     self.expected_output = [ 
      (2, True), 
      (3, False), 
      (4, True), 
      (5, False) 
     ] 

    def test_is_even(self): 
     real_res = [] 

     for arg, _ in self.expected_output: 
      real_res.append((arg, is_even(arg))) 

     msg_error = '\nFor %s Expected %s Got %s' 
     msg = [] 
     for res1, res2 in zip(real_res, self.expected_output): 
      if res1[1] != res2[1]: 
       msg.append(msg_error % (res1[0], res1[1], res2[1])) 


     self.assertEqual(real_res, self.expected_output, "".join(msg)) 


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

输出:

F 
====================================================================== 
FAIL: test_is_even (__main__.TestCase) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "test.py", line 29, in test_example 
    self.assertEqual(real_res, self.expected_output, ''.join(msg)) 
AssertionError: 
For 3 Expected True Got False 
For 5 Expected True Got False 

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

FAILED (failures=1) 
+0

如果我有50个测试,其中10个测试失败,将很难找到正在发生的事情。对于一小组简单的测试数据,它将非常方便和有用。谢谢:) – jinowolski 2011-06-14 22:08:48

+2

@jinowolski:真的,很高兴我们可以自定义错误消息尽可能多我编辑我的答案我不知道这是否适合你。 – mouad 2011-06-14 22:21:12

+0

但它仍然是1测试 – 2011-06-14 23:17:12

2

如果您使用的是pytest y OU可以走这条路:

import pytest                             

def is_even(number): 
    return True # quite 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 ==================== 
+0

也许mark参数化在其他答案贡献时并不存在,但这里的感觉就像是正确的答案。 – 2017-09-28 08:41:03

相关问题