假设我们想为(当前)仅实现两个例程sqrt
和ln
的(简单)数学库编写测试用例。除其他事项外,如果两个例程的输入为负,则它们都将引发ValueError
。因此,测试用例将如下所示:
import unittest
from my_math_lib import sqrt, ln
class TestSqrt(unittest.TestCase):
def test_negatives(self):
self.assertRaises(ValueError, sqrt, -5)
# ... any many other cases
class TestLn(unittest.TestCase):
def test_negatives(self):
self.assertRaises(ValueError, ln, -5)
# ... any many other cases
显然,除了要测试的功能外,两个测试用例TestSqrt.test_negatives
和TestLn.test_negatives
是相同的,重复完全相同的代码是一个坏主意。
是否可以自动生成此类测试用例?例如,在C / C ++中,可能已经实现了一个宏,该宏使用适当的函数名定义了测试代码。 Python中有类似的解决方案吗?
答案 0 :(得分:0)
@jonrsharpe提出了子类化的可能性,尽管有一个警告。您不能从unittest.TestCase
派生基类并在其中编写testXXX
,因为这也会被发现并执行,并且会失败。您需要混入:
class BaseTest:
def setUp(self):
self.tested = None
def test_negatives(self):
self.assertRaises(ValueError, self.tested, -5)
class TestSqrt(unittest.TestCase, BaseTest):
def setUp(self):
self.tested = sqrt
class TestLn(unittest.TestCase, BaseTest):
def setUp(self):
self.tested = log
这有效,但不好用,因为基类从TestCase
(assertRaises
)调用了一个方法,该方法不是从该方法派生的,因此每一个linter或IDE检查都会警告您这一点。
要解决该问题,您可以只使用一种实际的实现作为基类:
class TestSqrt(unittest.TestCase):
def setUp(self):
self.tested = sqrt
def test_negatives(self):
self.assertRaises(ValueError, self.tested, -5)
class TestLn(TestSqrt):
def setUp(self):
self.tested = log
class TestSomethingElse(TestSqrt):
def setUp(self):
self.tested = something_else
如果可以使用pytest,我将使用夹具参数化:
import pytest
@pytest.fixture(params=[sqrt, log])
def tested_function(request):
return request.param
def test_negatives(tested_function):
with pytest.raises(ValueError):
tested_function(-5)
def test_something_else(tested_function):
...
您当然也可以将其放入课堂。
警告:unittest
不起作用,或者至少我不知道一种干净的方法。