如何在模块级别的 pytest 脚本中定义要在夹具中使用的值?

How to define a value in a pytest script at module level to be used in a fixture?

我正在尝试在 pytest 脚本中使用模块级别的函数(而不是直接为变量赋值)定义一个字符串,该字符串将在范围为 'module' 的夹具中使用。 问题是,当在模块级别使用函数时,它会在 pytest 收集阶段进行评估 - 当 运行 pytest 在具有几个脚本的文件夹上时,fixture 使用最后评估的值。

是否有其他方法可以根据脚本在模块级别设置字符串?

这是我目前所拥有的,但没有完成任务:

my_script1.py:

import env_var as env

env.set_my_string('This string will be used in the module fixture')

test_first():
    # Do stuff

conf_test.py:

import pytest
import env_var as env

@pytest.fixture(scope='module', autouse=True)
def script_handler():
    txt = env.get_my_string()
    # Use txt
    yield

env_var.py:

_tmp_str = ''

def set_my_string(in_str)
    _tmp_str = in_str

def get_my_string():
    return _tmp_str

您可以通过 request fixture 中的 node 对象访问 fixture 中的测试模块,以及该模块中定义的任何变量或函数:

test_1.py

my_env = "test1var"

test_first():
    pass

test_2.py

my_env = "test2var"

test_first():
    pass

conftest.py

@pytest.fixture(scope='module', autouse=True)
def script_handler(request):
    txt = request.node.obj.my_var
    print(txt)
    yield

request.node 为您提供测试节点,而 obj 是模块级夹具的模块,因此您可以通过该变量访问模块中定义的对象。

为了说明 - 如果你运行这个:

$python -m pytest -v -s test_dir

您可以看到使用了模块特定值:

...
collected 2 items

test_dir/test_1.py::test_first test1var
PASSED
test_dir/test_2.py::test_first test2var
PASSED

如果出于某种原因你需要在别处保存模块特定的字符串(如评论中所述),你必须按模块保存它们,例如使用模块名称作为键:

env_var.py

my_vars = {}

def set_my_string(name, var):
    my_vars[name] = var

def get_my_string(name):
    return my_vars.get(name, "some_default")

test_1.py

from env_var import set_my_string

set_my_string(__name__, "test1var")

def test_first():
    pass

conftest.py

import pytest

from env_var import get_my_string


@pytest.fixture(scope='module', autouse=True)
def script_handler(request):
    module_name = request.node.obj.__name__
    print(get_my_string(module_name))
    yield

除了MrBean Bremen 的出色回答,我还找到了另一个解决方案: 在脚本文件中添加一个夹具,returns sting - 然后在 conf_test.py 文件中使用 request.getfixturevalue() 函数。

my_script1.py:

import pytest

@pytest.fixture(scope='module')
def my_var:
    return 'This string will be used in the module fixture'

test_first():
    # Do stuff

conf_test.py:

import pytest

@pytest.fixture(scope='module', autouse=True)
def script_handler():
    txt = request.getfixturevalue('my_var')
    # Use txt
    yield