gpt4 book ai didi

python - pytest:针对同一接口(interface)的不同实现的可重用测试

转载 作者:太空狗 更新时间:2023-10-29 18:08:12 26 4
gpt4 key购买 nike

假设我实现了一个名为 Bar 的实用程序(可能是一个类)在模块中 foo ,并为其编写了以下测试。

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

现在想象一下,将来我希望编写同一接口(interface)的不同实现。我希望这些实现能够重用为上述测试套件编写的测试:唯一需要更改的是

  1. 导入 Implementation
  2. <test data set 1> , <test data set 2>

所以我正在寻找一种以可重用的方式编写上述测试的方法,这将允许接口(interface)的新实现的作者能够通过将实现和测试数据注入(inject)到测试中来使用测试,而无需修改包含原始测试规范的文件。

在 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_test.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))

任何人(甚至是图书馆的客户)编写此接口(interface)的另一个实现

  • 可以重用 define_tests.py 中定义的测试集
  • 将自己的测试数据注入(inject)到测试中
  • 不修改任何原始文件

最佳答案

这是 parametrized test fixtures 的一个很好的用例.

您的代码可能如下所示:

from foo import Bar, Baz

@pytest.fixture(params=[Bar, Baz])
def Implementation(request):
return request.param

def test_one(Implementation):
assert Implementation().frobnicate()

这将使 test_one 运行两次:一次是在 Implementation=Bar 处,一次是在 Implementation=Baz 处。

请注意,由于实现只是一个固定装置,您可以更改其范围,或进行更多设置(可能实例化类,可能以某种方式配置它)。

如果与 pytest.mark.parametrize 装饰器一起使用,pytest 将生成所有排列。例如,假设上面的代码和这里的代码:

@pytest.mark.parametrize('thing', [1, 2])
def test_two(Implementation, thing):
assert Implementation(thing).foo == thing

test_two 将运行四次,配置如下:

  • 实现=酒吧,事情=1
  • 实现=酒吧,事情=2
  • 实现=Baz,事情=1
  • 实现=Baz,事情=2

关于python - pytest:针对同一接口(interface)的不同实现的可重用测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26266481/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com