想象一下我已经实现了一个名为的实用程序(可能是一个类)Bar
在一个模块中foo
,并为其编写了以下测试。
测试_foo.py:
from foo import Bar as Implementation
from pytest import mark
@mark.parametrize(<args>, <test data set 1>)
def test_one(<args>):
<do something with Implementation and args>
@mark.parametrize(<args>, <test data set 2>)
def test_two(<args>):
<do something else with Implementation and args>
<more such tests>
现在想象一下,将来我希望编写同一接口的不同实现。我希望这些实现能够重用为上述测试套件编写的测试:唯一需要更改的是
- 进口的
Implementation
-
<test data set 1>
, <test data set 2>
etc.
因此,我正在寻找一种以可重用的方式编写上述测试的方法,这将允许接口的新实现的作者能够通过将实现和测试数据注入其中来使用测试,而无需修改包含测试原始规范的文件。
在 pytest 中执行此操作的一个好的、惯用的方法是什么?
=================================================== =================
=================================================== =================
这是一个(不太漂亮但)有效的单元测试版本。
定义_测试.py:
# Single, reusable definition of tests for the interface. Authors of
# new implementations of the interface merely have to provide the test
# data, as class attributes of a class which inherits
# unittest.TestCase AND this class.
class TheTests():
def test_foo(self):
# Faking pytest.mark.parametrize by looping
for args, in_, out in self.test_foo_data:
self.assertEqual(self.Implementation(*args).foo(in_),
out)
def test_bar(self):
# Faking pytest.mark.parametrize by looping
for args, in_, out in self.test_bar_data:
self.assertEqual(self.Implementation(*args).bar(in_),
out)
v1.py:
# One implementation of the interface
class Implementation:
def __init__(self, a,b):
self.n = a+b
def foo(self, n):
return self.n + n
def bar(self, n):
return self.n - n
v1_测试.py:
# Test for one implementation of the interface
from v1 import Implementation
from define_tests import TheTests
from unittest import TestCase
# Hook into testing framework by inheriting unittest.TestCase and reuse
# the tests which *each and every* implementation of the interface must
# pass, by inheritance from define_tests.TheTests
class FooTests(TestCase, TheTests):
Implementation = Implementation
test_foo_data = (((1,2), 3, 6),
((4,5), 6, 15))
test_bar_data = (((1,2), 3, 0),
((4,5), 6, 3))
任何人(甚至是库的客户端)编写此接口的另一个实现
- 可以重用中定义的测试集
define_tests.py
- 将自己的测试数据注入到测试中
- 不修改任何原始文件