首页 > 解决方案 > 如何使用 pytest 在装饰器中使用命令行参数?

问题描述

语境

我想要实现的是拥有一个装饰器,它取决于命令行参数,将改变测试的运行方式:

import pytest
from functools import wraps


def magic():

    # obtain extra_bit
    extra_bit = ...

    def wrapper(f):
        if extra_bit:
            @wraps(f)
            def test_func(*args, **kwars):
                f(*args, **kwars)
        else:
            @wraps(f)
            def test_func(*args, **kwargs):
                assert 0

        return test_func

    return wrapper

将此装饰器称为:

@magic(4)
def test_this():
    assert 0

调用接口很重要,因为命令行参数不应该出现在这里(因为装饰器的用户从不使用它)。

从 pytest 文档解释

https://docs.pytest.org/en/latest/example/simple.html

在 pytest 中将命令行参数用作测试函数非常容易:

import pytest

def pytest_addoption(parser):
    parser.addoption('--extra_bit', action='store_true')

@pytest.fixture
def extra_bit(request):
    return request.config.getoption('--extra_bit')

然后在测试中使用它们

def test_this(extra_bit):
    assert extra_bit

但是,这些fixture 仅在用于test_函数定义时才有效,而不适用于测试模块中的任意函数。

问题

test_如果不是通过函数参数/夹具,我如何从 pytest 获取命令行参数?

标签: pythonpytest

解决方案


简短地回答

使用pytest_configureone 可以使该选项在conftest.py文件中可用。

conftest.py

import pytest

_EXTRA_BIT = False

def extra_bit():
    return _EXTRA_BIT

def pytest_addoption(parser):
    parser.addoption("--extra_bit", action="store_true")

def pytest_configure(config):
    global _EXTRA_BIT
    _EXTRA_BIT = config.getoption("--extra_bit")

测试插件.py

from conftest import extra_bit
from functools import wraps


def magic():

    # obtain extra_bit
    extra_bit = extra_bit()

    def wrapper(f):
        if extra_bit:
            @wraps(f)
            def test_func(*args, **kwars):
                f(*args, **kwars)
        else:
            @wraps(f)
            def test_func(*args, **kwargs):
                assert 0

        return test_func

    return wrapper

编辑:下面的旧答案使用不推荐使用 pytest.config的模块。

简短地回答

所以事实证明 pytest 确实通过pytest.config模块提供了该功能。相关文档在这里:https ://docs.pytest.org/en/latest/reference.html#_pytest.config.Config 。可以使用的功能就是getoption功能。

改编的例子

import pytest
from functools import wraps


def magic():

    # obtain extra_bit
    extra_bit = pytest.config.getoption('--extra_bit')

    def wrapper(f):
        if extra_bit:
            @wraps(f)
            def test_func(*args, **kwars):
                f(*args, **kwars)
        else:
            @wraps(f)
            def test_func(*args, **kwargs):
                assert 0

        return test_func

    return wrapper

推荐阅读