【问题标题】:How to define a value in a pytest script at module level to be used in a fixture?如何在模块级别的 pytest 脚本中定义要在夹具中使用的值?
【发布时间】:2021-03-29 07:52:20
【问题描述】:

我正在尝试在 pytest 脚本中使用模块级别的函数(而不是直接将值分配给变量)在 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

【问题讨论】:

    标签: python module pytest fixtures


    【解决方案1】:

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

    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
    

    如果出于某种原因您需要将特定于模块的字符串保存在其他地方(如 cmets 中所述),则必须按模块保存它们,例如使用模块名称作为键:

    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
    

    【讨论】:

    • 感谢您的回答。您写道,“请求”夹具也具有该模块中定义的功能,但我找不到它们。你知道它什么时候隐藏吗?此外,我更喜欢使用来自另一个模块的函数来设置字符串(例如我的示例中的 env.set_my_string() )。有没有办法做到这一点?
    • 这是行不通的——你会在每次调用函数时都会覆盖一个全局变量。你有需要这个的理由吗?至于函数——它们可以像我展示的变量一样被访问(最后它们都是对象)。不知道你所说的“找到他们”是什么意思。
    • 在模块级别使用变量将迫使脚本编写者(不一定是我)熟悉确切的知名变量名称。抱歉,我所说的“找到它们”是指在 PyCharm 的调试器中。但无论如何,它就像你说的那样有效,谢谢。
    • 脚本编写者必须知道如何设置模块级别的值。这可以通过设置一个如图所示的变量,或者覆盖一个函数,或者调用一些外部方法(如果它被实现来保存模块特定的值)来完成,但是他们无论如何必须知道那个 API。
    • 你是对的。如何实现保存模块特定值的外部方法(如您的第三个建议)?
    【解决方案2】:

    除了 MrBean Bremen 出色的答案外,我还找到了另一个解决方案: 在脚本文件中添加一个fixture,它返回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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-16
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      • 2015-06-27
      • 2021-06-28
      • 1970-01-01
      相关资源
      最近更新 更多