Pytest 使用固定装置比较几个 class 个实例

Pytest compare several class instances using fixtures

我正在学习 pytest,我正在尝试使用固定装置生成多个 class 实例,并将方法的结果与值进行比较。

比如我有下面的代码。在这种情况下,我有一个名为 building 的 class,它具有计算屋顶角度的方法。我正在生成 class 的两个实例,但我想将角度与两个不同的值进行比较。目前我正在与固定值 (12) 进行比较。

如何设置每个实例对应的值进行比较?

import pytest

from pywind.geometry import Building

params = [(60, 30, 6, 16, 0, 'gable'), (30, 50, 7, 13, 0, 'shed')] # Arguments

@pytest.fixture(params=params)
def building(request):
    building = Building(*request.param)
    return building

def test_roof_angle(building):
    assert building.roof_angle() == 12

我认为你正在尝试做的事情与夹具的概念背道而驰。来自 pytest 文档,fixture 页面上的第一句话:

The purpose of test fixtures is to provide a fixed baseline upon which tests can reliably and repeatedly execute.

我添加了对固定基线的强调。这里有 两个 基线:山墙和棚子。为了符合固定装置的概念,您应该考虑将山墙和棚子拆分成单独的固定装置:

@pytest.fixture(params=[60, 30, 6, 16, 0, 'gable'])
def gable(request):
    building = Building(*request.param)
    return building

@pytest.fixture(params=[30, 50, 7, 13, 0, 'shed'])
def shed(request):
    building = Building(*request.param)
    return building

然后为每个创建带有适当断言的测试:

def test_roof_angle_1(gable):
    assert building.roof_angle() == 12

def test_roof_angle_2(shed):
    assert building.roof_angle() == 23

当多个灯具应该 运行 用于相同的精确测试时,向 params 参数提供多个参数列表很有用。在 pytest fixture docs 的示例中,他们测试了来自不同 URL 的 SMTP 响应。

在你的例子中,如果你有不同的建筑类型,它们应该都具有相同的特征(即,它们都具有相同的屋顶角度),那么使用多个参数来自动计算将是有用和合适的-运行 测试多个灯具。您可以将其命名为 buildings_with_12roof,而不是使用通用的 "building" fixture。

如果我没理解错的话,你希望你的夹具不仅提供一个测试实例,还提供一堆预期值,以便在测试中进行比较。请记住,您可以根据需要传递任意数量的参数;但是,以可读的方式组织它们取决于您。例如,您可以引入一些同时包含建筑实例和预期角度的中间容器:

from collections import namedtuple


BuildingData = namedtuple('BuildingData', ('instance', 'expected_angle', ))


params = [(60, 30, 6, 16, 0, 'gable', 12),
          (30, 50, 7, 13, 0, 'shed', 42)]


@pytest.fixture(params=params)
def building(request):
    # all params except the last one are constructor args
    instance_args = request.param[:-1]
    instance = Building(*instance_args)
    # last param is the expected roof angle
    expected_angle = request.param[-1]
    return BuildingData(instance, expected_angle)


def test_roof_angle(building):
    assert building.instance.roof_angle() == building.expected_angle