从另一个灯具动态创建PyTest灯具参数

时间:2020-02-20 14:10:34

标签: python pytest fixtures

我有一个包含几个JSON文件的AWS S3目录,这些文件用作测试输入。

我创建了一个PyTest模块,该模块使用模块级fixture下载一次所有的JSON文件,然后运行多个测试函数-每个函数都通过JSON集进行参数化:

import pytest
import os
from tempfile import mkdtemp, TemporaryDirectory
from glob import glob

JSONS_AWS_PATH = 's3://some/path/'

def download_jsons():
    temp_dir = mkdtemp()
    aws_sync_dir(JSONS_AWS_PATH, temp_dir)
    json_filenames = glob(os.path.join(local_path, "*.json"))
    return json_filenames

@pytest.fixture(scope='module', params=download_jsons()) #<-- Invoking download_jsons() directly
def json_file(request):
    return request.param

def test_something(json_file):
   # Open the json file and test something

def test_something_else(json_file):
   # Open the json file and test something else

def test_another_thing(json_file):
   # you got the point...

该测试模块本身可以工作-唯一的痛点是如何在模块\会话末尾清除temp_dir
由于download_jsons()是直接被调用的,因此json_file固定装置甚至没有启动之前-它没有自己的上下文。因此,在完成所有测试后,我无法使其干净temp_dir

我想将download_jsons()本身作为模块\会话范围fixture。像这样:

fixture(scope='module')
def download_jsons():
   temp_dir = mkdtemp()
   # Download and as glob, as above
   yield json_filenames
   shutil.rmtree(temp_dir)

fixture(scope='module')
def download_jsons(tmpdir_factory):
    #...

如@Gabriela Melo所建议。

问题是如何使json_file返回的列表中的download_jsons()灯具参数化,而又不直接调用它呢?

我尝试使用mark.parametrizesetup_module()pytest_generate_tests(metafunc)来实现此解决方案-但无法实现我一直在寻找的确切功能。

2 个答案:

答案 0 :(得分:0)

这似乎是您要寻找的:https://docs.pytest.org/en/latest/tmpdir.html#the-tmpdir-factory-fixture

(使用Pytest的tmpdir_factory固定装置,并将json_file函数的范围设置为session而不是module

答案 1 :(得分:0)

如果您想使用资源进行参数化,固定装置将无法返回该资源(至少对于当前版本的pytest而言)。但是,您可以将设置/拆卸代码移到挂钩中-这还将通过pytest_generate_tests挂钩启用参数化。示例:在项目的根目录中,创建一个名为conftest.py的文件,其内容如下:

from tempfile import TemporaryDirectory
from pathlib import Path


def pytest_sessionstart(session):
    # this is where we create the temp dir and download the files
    session.config._tempdir = TemporaryDirectory()
    d = session.config._tempdir.name
    aws_sync_dir(JSONS_BLOBBY_PATH, d)
    session.config._json_files = Path(d).glob("*.json")


def pytest_sessionfinish(session):
    # this is where we delete the created temp dir
    session.config._tempdir.cleanup()


def pytest_generate_tests(metafunc):
    if "file" in metafunc.fixturenames:
        # parametrize the file argument with the downloaded files
        files = metafunc.config._json_files
        metafunc.parametrize("file", files)

您现在可以像往常一样在测试中使用file参数,例如

def test_ends_with_json(file):
    assert file.suffix == ".json"