【问题标题】:How can I make a factory for class-scope fixtures with pytest?如何使用 pytest 为类范围的固定装置创建工厂?
【发布时间】:2019-10-24 16:32:32
【问题描述】:

我有一组夹具,它们都做同样的事情,打开一个 json 文件并使其可用于测试类。

@pytest.fixture(scope="class")
def category_params(request):
    base_path = os.path.abspath(..)
    path = os.path.join(base_path, "data/category_params.json")
    with open(path, "r") as fp:
        category_params = json.load(f)
    return category_params

我为测试域中的所有不同测试类别重复此设置。这似乎是我应该为它编写一个函数的东西,但我不确定如何使用 pytest 来完成它。我相信我应该问如何制作夹具工厂,即制作其他夹具对象的 pytest 夹具对象。

【问题讨论】:

  • 为什么不能创建一个函数并从每个夹具调用它?它会工作得很好。也可以尝试制作夹具工厂;我不记得这样做了,但它也应该可以工作。
  • 我想将代码量保持在最低限度,并制作一个函数并从每个夹具调用它会增加一点。我想使用夹具工厂,但不确定如何实现。
  • 您的意思是指单个夹具函数会加载不同的 JSON 文件吗?
  • 每个测试类都需要不同的 JSON 文件。我不知道这是否意味着为每个类创建一个单独的夹具,或者只是调用一个夹具函数来加载该类的参数。

标签: python pytest fixtures


【解决方案1】:

你可以parametrize your fixture函数,这意味着每个测试可以给它一个不同的JSON文件来加载:

import pytest
import os
import json


@pytest.fixture(scope="class")
def json_content(request):
    base_path = os.path.abspath(..)
    path = os.path.join(base_path, request.param)

    with open(path, "r") as fp:
        data = json.load(fp)

    return data


@pytest.mark.parametrize("json_content", ["abc.json"], indirect=True)
def test_a(json_content):
    print(json_content)


@pytest.mark.parametrize("json_content", ["xyz.json"], indirect=True)
def test_b(json_content):
    print(json_content)

注意:测试示例未显示每个类使用相同的夹具,但这不是演示参数化所必需的。

【讨论】:

    【解决方案2】:

    (警告:我没有测试此代码。)

    我认为这样的事情应该工作。

    def make_fixture_for(data_file):
        @pytest.fixture(scope="class")
        def params_fixture(request):
            base_path = os.path.abspath(..)
            path = os.path.join(base_path, data_file)
            with open(path, "r") as fp:
                return json.load(fp)
        return params_fixture
    
    foo_params = make_fixture_for("data/foo.json")
    bar_params = make_fixture_for("data/bar.json")
    

    这在模块的顶层定义了fixture函数,pytest 期望它们, 但以一种紧凑的方式这样做。

    这可以在数据文件名的一个循环中完成,并使用globals 将它们放入模块的顶级上下文中,但这感觉就像是难以理解的魔法。上面的代码很简单。

    也许pytest 不喜欢内部有很多同名的fixture 函数;然后在功能上设置.__name__ 可能有帮助,也可能没有;再说一遍,这段代码我没有测试,我不记得pytest的fixture发现过程的细节了。

    【讨论】:

    • 这实际上是一种很好的分解夹具的方法,并且避免了像我的示例中那样为每个测试方法声明@pytest.mark.parametrize 的相同文件。我只是建议您修复您的示例(make_fixture_for 前面缺少def)并在测试类中演示该应用程序,即使它相当明显。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多