本文共 6361 字,大约阅读时间需要 21 分钟。
Pytest request fixture 是 pytest 中一个非常有用的功能,它能够为测试提供丰富的元数据,帮助开发者更好地理解和管理测试用例。以下将从基础到高级功能详细说明 request fixture 的使用方法,并通过实际项目示例展示其应用场景。
request fixture 是一个特殊的 fixture,它提供了当前请求测试函数的信息。通过查看官方文档,可以了解到 request fixture 的具体用途和功能。
当前测试用例的节点对象,表示当前执行的测试用例。可以通过该对象获取测试用例的名称、文件路径、测试类等信息。
import pytest@pytest.fixturedef my_fixture(request): node = request.node print(f"Current test case: {node.name}") print(f"Test file path: {node.fspath}") print(f"Test class: {node.getparent}") 运行上述代码,输出结果如下:
Current test case: test_demoTest file path: /Users/pxl/test_dir/test_demo.pyTest class:>
通过 request.node,我们可以获取当前测试用例的相关信息,包括名称、文件路径和父类对象等。
前运行的配置对象,表示当前 pytest 的配置信息。可以使用该对象获取命令行参数、配置文件设置等信息。
@pytest.fixturedef my_fixture(request): config = request.config print(f"Command line arguments: {config.option}") print(f"INI file options: {config.getini('markers')}") 运行上述代码,输出结果如下:
Command line arguments: {}INI file options: [('p0', '冒烟'), ('p1', '功能')] 通过 request.config,我们可以获取当前 pytest 的配置信息,包括命令行参数和配置文件中的选项。
当前 fixture 的参数,表示当前 fixture 的实例所需的参数值。
@pytest.fixture(params=[1, 2, 3])def my_fixture(request): param_value = request.param print(f"Current parameter value: {param_value}") return param_value 运行上述代码,输出结果如下:
Current parameter value: 1
通过 request.param,我们可以获取当前 fixture 实例所需的参数值。
返回当前 fixture 的名称。
@pytest.fixturedef my_fixture(request): fixture_name = request.fixturename print(f"Current fixture name: {fixture_name}") 运行上述代码,输出结果如下:
Current fixture name: my_fixture
通过 request.fixturename,我们可以获取当前 fixture 的名称。
返回当前测试函数所使用的所有 fixture 的名称列表。
@pytest.fixturedef my_fixture(request): passdef test_example(my_fixture, request): fixture_names = request.fixturenames print(f"Current fixture name: {fixture_names}") 运行上述代码,输出结果如下:
Current fixture name: ['my_fixture']
通过 request.fixturenames,我们可以获取当前测试函数使用的所有 fixture 的名称列表。
当前测试类的类对象。
class TestClass: @pytest.fixture def my_fixture(self, request): class_obj = request.cls print(f"Current class object: {class_obj}") 运行上述代码,输出结果如下:
Current class object:
通过 request.cls,我们可以获取当前测试类的类对象。
在 fixture 完成后执行指定的函数。
@pytest.fixturedef my_fixture(request): def finalizer_func(): print("Finalizer function called") request.addfinalizer(finalizer_func) print("Fixture setup") 运行上述代码,输出结果如下:
Fixture setupFinalizer function called
通过 request.addfinalizer(finalizer_func),我们可以注册一个在 fixture 执行完毕后执行的函数。
为当前测试用例或 fixture 应用指定的 marker。
@pytest.fixturedef my_fixture(request): request.applymarker(pytest.mark.slow)
运行上述代码,输出结果如下:
通过 request.applymarker(marker),我们可以为当前 fixture 添加标记。
获取命令行选项的值。
@pytest.fixturedef my_fixture(request): my_option = request.config.getoption("--my_option") print(f"Value of --my_option: {my_option}") 运行上述代码,输出结果如下:
Value of --my_option: None
通过 request.config.getoption(name),我们可以获取命令行选项的值。
当前测试用例所属的模块对象。
def my_fixture(request): module_obj = request.module print(f"Current module object: {module_obj}") 运行上述代码,输出结果如下:
Current module object:
通过 request.module,我们可以获取当前测试用例所属的模块对象。
参数化 fixture 的参数索引。
@pytest.fixture(params=[1, 2, 3])def my_fixture(request): param_value = request.param param_index = request.param_index print(f"Current parameter value: {param_value}") print(f"Current parameter index: {param_index}") return param_value 运行上述代码,输出结果如下:
Current parameter value: 1Current parameter index: 0
通过 request.param_index,我们可以获取当前参数在参数列表中的索引。
当前测试用例的关键字集合。
@pytest.fixturedef my_fixture(request): keywords = request.keywords print(f"Current test keywords: {keywords}") 运行上述代码,输出结果如下:
Current test keywords: []
通过 request.keywords,我们可以获取当前测试用例的关键字集合。
获取已注册的 fixture 对象的值。
import pytest@pytest.fixturedef my_fixture(): return "Hello, Fixture!"def test_example(request): fixture_value = request.getfixturevalue("my_fixture") assert fixture_value == "Hello, Fixture!" 运行上述代码,输出结果如下:
Hello, Fixture!
通过 request.getfixturevalue(fixturename),我们可以获取已注册的 fixture 对象的值。
到这里,request fixture 的常用属性和方法应该已经了解差不多了。更多属性和方法,可以参考官方文档。
接下来我们就利用 request 属性实现数据库环境的切换。看实现代码:
conftest.pydef pytest_addoption(parser): parser.addoption("--test", action="store_true", help="Run tests in test mode")@pytest.fixture(scope="session")def config_parser(request): class Clazz(object): config = ConfigParser() config.read(config_path) section = 'test' if request.config.getoption("--test") else 'prod' log.info(f"section: {config.sections()}") db_host = config.get(section, 'host') db_port = config.get(section, 'port') db_username = config.get(section, 'username') db_password = config.get(section, 'password') db_database = config.get(section, 'database') api_url = config.get(section, 'url') return Clazz@pytest.fixture(scope="session")def db_connection(config_parser): db_conn = MySQLDB( config_parser.db_host, int(config_parser.db_port), config_parser.db_username, config_parser.db_password, config_parser.db_database ) yield db_conn db_conn.close() config_parser 是一个会话级别的 fixture,它返回一个配置解析器对象。这个配置解析器对象可以读取配置文件,并根据传入的命令行参数 --test 来确定读取哪个配置文件的特定部分(测试环境或生产环境)。
具体流程如下:
在 pytest_addoption 函数中,通过调用 parser.addoption() 方法来添加一个命令行选项 --test,它的作用是告诉 pytest 在测试模式下运行。
在 config_parser fixture 中,我们首先创建了一个名为 Clazz 的类,它包含了从配置文件中读取的各个配置项的值。
根据传入的 --test 参数值,决定使用测试环境还是生产环境的配置。如果 --test 参数被指定,则使用配置文件中的 test 部分,否则使用 prod 部分。
通过 config.get() 方法获取具体的配置项的值,例如 db_host、db_port、db_username 等。
最后,将 Clazz 类作为返回值,供其他测试代码使用。
db_connection 是一个会话级别的 fixture,它返回一个数据库连接对象。
具体流程如下:
在 db_connection fixture 中,我们创建了一个 MySQLDB 对象,将从 config_parser fixture 中获取的数据库连接参数传入。
使用 yield 语句将数据库连接对象返回给测试代码。yield 使得这个 fixture 可以在测试期间提供数据库连接,而在测试完成后继续执行下面的代码。
在 yield 之后的代码将在测试完成后执行,这里使用 db_conn.close() 来关闭数据库连接。
可以看到我们正是使用 request.config.getoption 这个方法来获取命令行选项的值。
通过使用 pytest 的 fixture 来管理测试环境和资源的初始化和清理,我们可以确保在整个测试会话期间只进行一次配置解析和数据库连接操作,避免重复的开销和不必要的操作。
到这里我们已经攻克了一个知识点 request,不仅介绍了它的基本用法,也介绍了笔者在工作中真实使用场景。希望这些内容能对你有所帮助。如果你觉得有趣,可以点击下方小卡片领取更多精彩内容!
转载地址:http://fjafk.baihongyu.com/