Pytest-将多个灯具参数组合到单个灯具中以优化灯具实例化

问题描述 投票:3回答:1

我有一个现有的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_ITEMSB_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]我也有一个昂贵的...

python unit-testing pytest fixtures
1个回答
0
投票

不是一个好答案,更多的是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)
© www.soinside.com 2019 - 2024. All rights reserved.