如何在测试之间共享全局变量?

2024-05-17 05:27:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我在conftest.py中有一个全局变量,并在测试中使用它。例如:

conftest.py

api_version = 'v25'
api_url = 'http://www.foobar.com/' + api_version

测试foo.py

from conftest import api_url
import requests

@pytest.fixture
def data():
    return requests.request("GET", api_url)

test_bar(data):
    assert data is not None

现在我想能够从cmd更改api_版本来测试其他api版本。所以我修改conftest.py的方式如下:

conftest.py

api_url = None

def pytest_addoption(parser):
    parser.addoption("--api_version", action="store", default="v25", help="By default: v25")

@pytest.fixture(autouse=True, scope='session')
def cmd_param(pytestconfig):
    api_version = pytestconfig.getoption("--mobile_api_ver").lower()
    global api_url
    if api_version in ['v24', 'v25', 'v26', 'v27']:
        api_url = 'http://www.foobar.com/' + api_version
    else:
        raise ValueError('Unknown api version: ' + api_version)

但这并不像我预期的那样工作,因为所有导入都在fixture之前执行,而test_foo importapi_url=None在cmd_param fixture重新定义它之前。 然后我编写get_api_url方法并从测试模块调用它:

conftest.py

api_url = None

def pytest_addoption(parser):
    parser.addoption("--api_version", action="store", default="v25", help="By default: v25")

@pytest.fixture(autouse=True, scope='session')
def cmd_param(pytestconfig):
    api_version = pytestconfig.getoption("--mobile_api_ver").lower()
    global api_url
    if api_version in ['v24', 'v25', 'v26', 'v27']:
        api_url = 'http://www.foobar.com/' + api_version
    else:
        raise ValueError('Unknown api version: ' + api_version)

def get_api_url():
    return api_url

但现在我也被迫改变了test_foo.py:

测试foo.py

from conftest import get_api_url
import requests

@pytest.fixture
def data():

    return requests.request("GET", get_api_url())

test_bar(data):
    assert data is not None

它起作用了,但解决方案看起来很尴尬。有没有更优雅的方法使用自定义命令选项而不更改测试文件?


Tags: pytestimportnoneapiurldatafoo
3条回答

注意:现在不推荐使用pytest_命名空间

pytest提供了在会话中使用一些全局变量的方法。这些变量也可以由fixture使用。

这些变量是通过pytest钩子控制的。

import pytest

def pytest_namespace():
    return {'my_global_variable': 0}

@pytest.fixture
def data():
    pytest.my_global_variable = 100

def test(data):
    print pytest.my_global_variable

我不会搞全局变量。 只需定义fixture以返回值并在测试中使用该fixture: 类似于@milo发布的内容,但简单得多。

此外,您还定义了--api_versionCLI选项,但访问了fixture中的--mobile_api_ver选项。另外,您的测试只是检查一个response对象不是None,它永远不是None,所以assert语句将始终通过,即使response是404状态,请参阅inline comments。

下面是一些可以工作的代码:

conftest.py的内容

import pytest


def pytest_addoption(parser):
    parser.addoption("--api_version", action="store", default="v25", help="By default: v25")


@pytest.fixture(scope='session')
def api_url(pytestconfig):
    api_version = pytestconfig.getoption("--api_version").lower()
    if api_version in ['v24', 'v25', 'v26', 'v27']:
        return 'http://www.foobar.com/' + api_version
    else:
        raise ValueError('Unknown api version: ' + api_version)

试验内容

import pytest
import requests


@pytest.fixture
def data(api_url):  # probably a good idea to rename your fixture to a api_response or change what fixture returns.
    return requests.get(api_url)


def test_bar(data):
    print(data.text)
    # below you are not testing data, but merely checking that response object is not None
    assert data is not None  # this will always pass

    # you probably want to test status code and response content
    assert data.status_code == 200
    assert data.json()

运行测试: pytest -vvv --api_version v24 test_foo.py

根据docs,已在版本4.0中删除pytest_namespace

可以使用pytest_configure来共享全局变量。

示例:

import pytest

def pytest_configure():
    pytest.my_symbol = MySymbol()

相关问题 更多 >