我有一个现有的pytest
测试,该测试使用一些预定义的列表来测试它们全部的叉积:
A_ITEMS = [1, 2, 3]
B_ITEMS = [4, 5, 6]
C_ITEMS = [7, 8, 9]
我还有一个昂贵的灯具,其内部条件取决于A和B项(而不是C),称为F:
class Expensive:
def __init__(self):
# expensive set up
time.sleep(10)
def check(self, a, b, c):
return True # keep it simple, but in reality this depends on a, b and c
@pytest.fixture
def F():
return Expensive()
目前,我有一个简单的方法,可以简单地设置测试函数的参数:
@pytest.mark.parametrize("A", A_ITEMS)
@pytest.mark.parametrize("B", B_ITEMS)
@pytest.mark.parametrize("C", C_ITEMS)
def test_each(F, A, B, C):
assert F.check(A, B, C)
此测试F与A,B和C项的所有组合,但是它通过Expensive
夹具为every测试构造了一个新的F
实例。更具体地说,它通过夹具F重新构建新的Expensive
用于A,B和C的每种组合。
这是非常低效的,因为当A和B的值发生变化时,我只需要构造一个新的Expensive
,而在所有C的测试之间它们都不是必需的。
[我想以某种方式将F
固定装置与A_ITEMS
和B_ITEMS
列表结合,以便F固定装置每次对C的值进行一次实例化一次新实例。
[我的第一种方法涉及将A和B列表分成各自的固定装置,并将它们与F固定装置结合在一起:
class Expensive:
def __init__(self, A, B):
# expensive set up
self.A = A
self.B = B
time.sleep(10)
def check(self, c):
return True # keep it simple
@pytest.fixture(params=[1,2,3])
def A(request):
return request.param
@pytest.fixture(params=[4,5,6])
def B(request):
return request.param
@pytest.fixture
def F(A, B):
return Expensive(a, b)
@pytest.mark.parametrize("C", C_ITEMS)
def test_each2(F, C):
assert F.check(C)
尽管这会测试所有组合,但不幸的是,这会为每个测试创建Expensive
的新实例,而不是将A和B的每个项目组合为一个可为C的每个值重用的单个实例。
我研究了间接灯具,但是我看不到将多个列表(即A和B项目都发送到一个灯具)的方法。
我可以使用pytest采取更好的方法吗?本质上,我要做的是最小化Expensive
的实例化次数,因为它取决于项A和B的值。]
注:我已经尝试简化此过程,但是实际情况是F代表创建一个新流程,A和B是该流程的命令行参数,而C只是传递给该流程的值通过插座。因此,我希望能够将C的每个值发送给该进程,而不必每次C更改时都重新创建它,但是显然,如果A或B更改,我需要重新启动它(因为它们是该进程的命令行参数)。] >
[我有一个现有的pytest测试,该测试使用一些预定义的列表来测试它们的叉积:A_ITEMS = [1、2、3] B_ITEMS = [4、5、6] C_ITEMS = [7、8, 9]我也有一个昂贵的...
不是一个好答案,更多的是hack-无论如何,我都会发布它,也许有人对如何使用标准pytest方法执行此操作有更好的主意(至少应该起作用)。基本上,这扩展了上面的建议,为最后使用的参数提供了额外的静态缓存,以避免在不需要时创建新的Expansive
:
@pytest.fixture(params=A_ITEMS)
def A(request):
return request.param
@pytest.fixture(params=B_ITEMS)
def B(request):
return request.param
lastAB = None
lastF = None
@pytest.fixture
def F(A, B):
global lastAB, lastF
if (A, B) != lastAB:
lastAB = (A, B)
lastF = Expensive(A, B)
return lastF
@pytest.mark.parametrize("C", C_ITEMS)
def test_each(F, C):
assert F.check(C)