Pytest使用fixture来比较几个类实例

时间:2018-05-02 09:33:22

标签: python-3.x pytest

我正在学习pytest,我试图使用灯具生成几个类实例,并将方法的结果与值进行比较。

例如,我有以下代码。在这种情况下,我有一个名为building的类,它有一个计算屋顶角度的方法。我正在生成该类的两个实例,但我想将角度与两个不同的值进行比较。目前我正在与固定值(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

2 个答案:

答案 0 :(得分:1)

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

  

测试装置的目的是提供一个固定基线,测试可以可靠地重复执行。

我强调固定基线。这里有两个基线:山墙和棚屋。为了符合夹具的概念,你应该考虑将山墙拆分成独立的夹具:

@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的示例中,他们测试的SMTP响应应该与不同的URL相同。

在你的情况下,如果你有不同的建筑类型应该都具有相同的特征(即,它们都具有相同的屋顶角度),那么使用多个参数自动运行将是有用和合适的。测试多个灯具。您可以将其命名为buildings_with_12roof,而不是使用通用的“建筑”夹具。

答案 1 :(得分:1)

如果我理解正确,您希望您的灯具不仅提供经过测试的实例,还要提供一系列要在测试中进行比较的预期值。请记住,您可以根据需要传递尽可能多的参数;但是,由您自己以可读的方式组织它们。例如,您可以引入一些同时包含构建实例和预期角度的中间容器:

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