我有一个基本的 Pytest 测试套件正在运行,我需要在运行时根据配置/参数动态参数化固定装置。
我的测试套件的“核心”是一个会话范围的固定装置,它根据一些自定义 CLI 参数执行一些“非常”昂贵的初始化,并且所有测试都使用此固定装置。稍微简单一点,将夹具视为提供到服务器的远程连接以运行测试,初始化涉及配置该服务器上的操作系统/依赖项(因此它昂贵且仅限会话范围),并且 CLI 参数指定操作系统/环境配置方面。 这对于单独的测试运行非常有用,但现在我想使用这个测试套件并在一系列不同的测试配置上运行整个测试。配置列表需要在运行时根据配置文件和一些附加 CLI 参数确定。
据我了解,在 Pytest 中执行此类操作的“明显”方法是参数化我的初始化装置。但问题是我需要根据其他参数动态地执行此操作;看起来您可以调用一个函数来填充
params
中的
@pytest.fixture
列表,但该函数无法访问 Pytest CLI 参数,因为参数解析尚未发生。我已经设法弄清楚如何通过实现pytest_generate_tests
来使用
间接参数化动态参数化每个测试,并利用夹具缓存来确保每个唯一的夹具配置实际上只初始化一次,即使实际上,每次测试都会对夹具进行参数化。这是可行的,尽管 Pytest 是否正式支持这一点值得怀疑。有没有更好的方法来实现我在这里想做的事情? “正确”的方式
def generate_parameters():
# This is just a plain function, and arg parsing hasn't happened yet,
# so I can't use Pytest options to generate my parameters
pass
@pytest.fixture(scope="session", params=generate_parameters())
def expensive_init_fixture(pytestconfig, request):
# Do initialization based on CLI args and request.param
pass
@pytest.fixture(scope="session")
def expensive_initialization_fixture(pytestconfig, request):
# Do initialization based on CLI args and request.param
pass
def pytest_generate_tests(metafunc):
if 'expensive_init_fixture' in metafunc.fixturenames:
parameters = [] # Generate parameters based on config in metafunc.config
metafunc.parametrize('expensive_init_fixture', parameters, scope="session", indirect=True)
我需要在配置选项关闭时生成特定参数,并在配置选项打开时将其他值添加到参数集中。并且基本上不会一直生成所有测试变体,而是仅在合适时生成所有测试变体,而不是生成所有测试并在不满足条件时跳过它们。
我能想到的回避这个问题的唯一方法是使用环境参数将数据传递给 pytest,即类似:
ENABLE_IT=True pytest ...
然后在里面使用第一种方法,但是
os.environ.get('ENABLE_IT', 'False')
虽然很难看,但可以用。快问。当您使用--collect-only
调用 pytest 时,您的工作解决方案是否正确显示测试名称,或者您不关心这一点?
效果很好。
在conftest.py中:
import pytest
def pytest_addoption(parser: pytest.Parser):
parser.addoption("--python", type=str, default="3.12",
help="Run integration tests with these versions of python")
def pytest_configure(config: pytest.Config):
pythons = config.option.python.split()
class AllPython:
@pytest.fixture(scope="session", params=pythons)
def python_version(self, request: pytest.FixtureRequest):
"python major version(s) to use"
return request.param
config.pluginmanager.register(AllPython())
您可以在
pytest_configure
中根据需要动态创建“插件类”。这意味着您可以根据需要完全动态地计算参数列表。