Python的pytest框架(6)--测试钩子 (hooks)

在编写测试时遇到需要在特定时间点执行特定操作的需求,比如初始化、资源管理、错误处理、性能监控或报告定制等,测试钩子就是解决这类痛点的强大工具。它们能帮助我们保持测试代码的整洁,同时提升测试的效率和灵活性。

目录

1. 钩子函数的概念

2. 常见的钩子函数以及如何使用它们

conftest.py 文件中的钩子:

测试会话钩子:

测试运行钩子:

测试用例钩子:

测试收集钩子:

3. 定制自己的钩子函数

4. 具体使用实例

在conftest.py文件中定义钩子:

conftest.py

test_sample.py

执行测试

输出示例

自定义插件来定义和使用测试钩子

1-创建插件

2-使用自定义插件

方法 A: 在命令行中指定插件

方法 B: 在pytest配置文件中指定插件


1. 钩子函数的概念

钩子函数是Pytest框架中预定义的一系列方法,这些方法会在测试执行过程中的特定时间点被调用。通过实现这些钩子方法,我们可以介入到测试生命周期的各个环节,比如初始化测试环境、执行前的准备、测试后清理、处理测试失败情况等,而无需直接修改Pytest的核心代码。这使得测试代码更加灵活和可扩展。

2. 常见的钩子函数以及如何使用它们

pytest提供了一系列的钩子函数,以下是一些常见的钩子:

conftest.py 文件中的钩子:

pytest_addoption(parser): 允许在命令行中添加自定义选项。
pytest_configure(config): 在所有命令行选项和ini文件配置后,配置测试环境时调用。
pytest_unconfigure(config): 在测试会话结束时调用,用于清理资源。

测试会话钩子:

pytest_sessionstart(session): 在测试会话开始时调用。
pytest_sessionfinish(session): 在测试会话结束时调用。

pytest_report_teststatus: 控制测试结果的输出格式。

测试运行钩子:

pytest_runtest_protocol(item, nextitem): 在每个测试用例执行前后调用,控制测试的执行流程。

测试用例钩子:

pytest_runtest_setup(item): 在每个测试用例的setup之前调用。
pytest_runtest_call(item): 调用测试用例函数。
pytest_runtest_teardown(item): 在每个测试用例的teardown之后调用。

测试收集钩子:

pytest_collection_modifyitems(session, config, items): 允许修改测试用例列表。

3. 定制自己的钩子函数

可以通过定义函数并使用特定的装饰器来创建自己的钩子函数。例如,如果想在每个测试用例执行前后打印一条消息,可以这样做:

import pytest

@pytest.hookimpl(tryfirst=True)
def pytest_runtest_logstart(nodeid):
    print(f"Test starting: {nodeid.split('::')[-1]}")

@pytest.hookimpl(tryfirst=True)
def pytest_runtest_logfinish(nodeid):
    print(f"Test finished: {nodeid.split('::')[-1]}")

这里的tryfirst=True参数表示这个钩子函数将在其他钩子函数之前执行。

4. 具体使用实例

在conftest.py文件中定义钩子:

我们通过一个完整的例子来展示如何在pytest中使用钩子函数来控制测试流程。

创建一个简单的测试场景,其中包括:

自定义fixture:用于演示基础的测试资源管理。

测试钩子:在测试开始前打印消息、在每个测试用例前后执行特定操作,并在测试结束时生成一个简短的报告。

确保我们的环境中安装了pytest。接下来,创建以下文件结构:

my_project/
│
├── tests/
│   ├── conftest.py
│   └── test_sample.py
└── requirements.txt

conftest.py

在tests/conftest.py文件中,我们定义钩子函数和一个fixture:

# tests/conftest.py

import pytest

# 自定义fixture
@pytest.fixture(scope='function')
def my_fixture():
    print("\nSetting up my_fixture...")
    yield
    print("Tearing down my_fixture...")

# 测试开始前的钩子
def pytest_sessionstart(session):
    print("pytest_sessionstart: 开始整个测试会话,准备环境...")

# 每个测试用例开始前的钩子
def pytest_runtest_setup(item):
    print(f"pytest_runtest_setup: 准备执行测试 {item.nodeid}")

# 每个测试用例结束后的钩子
def pytest_runtest_teardown(item, nextitem):
    print(f"pytest_runtest_teardown: 清理测试 {item.nodeid}, 下一个测试: {nextitem.nodeid if nextitem else '无'}")

# 整个测试会话结束后的钩子
def pytest_sessionfinish(session, exitstatus):
    print(f"pytest_sessionfinish: 测试会话结束,退出状态码: {exitstatus}")
    print("执行了一些清理工作...")

# 使用pytest_report_teststatus来改变测试结果的输出文本和颜色:
def pytest_report_teststatus(report, config):
    if report.when == 'call':
        if report.outcome == 'passed':
            # 绿色表示通过
            return ("通过", f"\033[32m{report.outcome}\033[0m", "")
        elif report.outcome == 'failed':
            # 红色表示失败,并附加失败信息的第一行
            return ("失败", f"\033[31m{report.outcome}: {report.longrepr.splitlines()[0]}\033[0m", "")
        elif report.outcome == 'skipped':
            # 蓝色表示跳过
            return ("跳过", f"\033[34m{report.outcome}: {report.wasxfail}\033[0m", "")
#颜色代码\033[XXm和\033[0m是ANSI转义序列,用于控制终端文本的颜色和样式

test_sample.py

然后,在tests/test_sample.py中编写我们的测试用例,使用上面定义的fixture:

# tests/test_sample.py

import pytest

def test_case1(my_fixture):
    assert True, "测试用例1通过"

def test_case2(my_fixture):
    assert False, "测试用例2失败,期望断言失败"

执行测试

保存以上文件后,在项目根目录下运行pytest:

pytest tests/

输出示例

执行上述命令后,你将看到类似以下的输出,展示了不同钩子函数在测试过程中的调用时机:

pytest_sessionstart: 开始整个测试会话,准备环境...
collecting ... collected 2 items

test_sample.py 
Setting up my_fixture...
pytest_runtest_setup: 准备执行测试 tests/test_sample.py::test_case1
Tearing down my_fixture...
pytest_runtest_teardown: 清理测试 tests/test_sample.py::test_case1, 下一个测试: tests/test_sample.py::test_case2
Setting up my_fixture...
pytest_runtest_setup: 准备执行测试 tests/test_sample.py::test_case2
Tearing down my_fixture...
pytest_runtest_teardown: 清理测试 tests/test_sample.py::test_case2, 下一个测试: 无
pytest_sessionfinish: 测试会话结束,退出状态码: 1
执行了一些清理工作...

============================== 1 passed, 1 failed in 0.05s ==============================

这个例子展示了如何使用pytest的钩子函数来控制测试流程,包括设置和清理测试环境、以及在测试会话的各个阶段执行自定义操作。

自定义插件来定义和使用测试钩子

1-创建插件

首先,创建一个新的Python模块(例如,命名为my_custom_plugin.py),并在其中定义你的钩子函数:

# my_custom_plugin.py

import pytest

def pytest_sessionstart(session):
    """
    在整个测试会话开始时被调用。
    """
    print(">>> 自定义插件:测试会话开始,执行初始化操作...")

def pytest_sessionfinish(session, exitstatus):
    """
    在整个测试会话结束时被调用。
    """
    print(">>> 自定义插件:测试会话结束,执行清理操作...")

2-使用自定义插件

要在测试套件中使用这个插件,有几种方法:

方法 A: 在命令行中指定插件

当你从命令行运行pytest时,可以通过-p或--plugin选项指定你的插件:

pytest -p my_custom_plugin tests/
方法 B: 在pytest配置文件中指定插件

你也可以在pytest的配置文件(如pytest.ini、tox.ini或setup.cfg)中声明你的插件:

# pytest.ini 或其他配置文件
[pytest]
addopts = -p my_custom_plugin

为了保持项目的组织性和钩子的可重用性,推荐的做法还是将它们放在适当的conftest.py文件中。这样不仅便于管理,也使得项目结构更加清晰。如果需要对特定测试文件或目录应用更为细致的控制,可以在该目录下放置一个conftest.py来局部覆盖或扩展全局的钩子定义。

希望以上内容能帮助大家合理有效使用测试钩子

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python Request Pytest Pytest-HTML 集成的 Api 自动化测试框架 是一款基于 Python 编程语言的自动化测试框架,主要用于对 API 接口进行自动化测试。该框架通过使用 Python 编写测试脚本和调用 Request 库和 Pytest 框架来实现 API 测试,并且生成可视化报告,提高测试效率和可观性。 使用 Python Request Pytest Pytest-HTML 集成的 Api 自动化测试框架 进行 API 自动化测试,可以实现以下功能: 1. 自动化执行 API 接口的测试用例,提高测试效率和准确性。 2. 使用 Pytest 框架,可以灵活地编写测试脚本,支持各种测试场景和用例。 3. 使用 Request 库,可以方便地发送 HTTP 请求,并对响应结果进行处理。 4. 结合使用 Pytest-HTML,可以生成易于阅读的测试报告,包括测试结果、测试用例执行情况、错误信息等。 在使用这个框架的过程中,开发人员可以遵循一些最佳实践,例如: 1. 编写清晰明了的测试用例,并保持测试脚本的结构和格式清晰。 2. 使用参数化测试功能,以确保测试用例的完备性和可扩展性。 3. 在测试执行前,准备好测试数据和测试环境,并确保测试用例的执行顺序和前后端接口的依赖关系正确。 总之,Python Request Pytest Pytest-HTML 集成的 Api 自动化测试框架 是一款功能强大、简单易用且可扩展的自动化测试框架,适用于任何需要对 API 接口进行自动化测试的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值