pytest之钩子函数

在pytest中钩子函数(hook functions)是用来自定义和扩展 pytest 的功能的关键机制。这些钩子函数可以在 pytest 的配置文件中或者插件中实现,用于干预测试执行的不同阶段和行为,这篇文章主要用来记录他不同钩子函数的使用

我们在开发自动化测试平台的时候其实可以借助于钩子函数来调用pytest测试脚本

首先简单定义的我们的测试函数如下test_demo.py:

def test_one():
    a = 100
    assert a < 100


def test_two():
    a = 100
    assert a == 100


def test_three():
    a = 200
    assert a > 100

上面就是我们的测试函数了,那我们一切以测试函数为准

我们钩子函数,我们都在pytest这个项目目录的根目录下创建我们的conftest.py文件,这样执行pytest测试的时候会自动触发我们这个文件中钩子函数

钩子函数之:pytest_collection_modifyitems(session, config, items)

1.用于修改或者重新排序收集到的测试项(test items),在items这个参数中

2.可以通过这个钩子来动态地过滤测试用例或者改变它们的执行顺序

下面是我们定义的函数:

def pytest_collection_modifyitems(session, config, items):
    """
    :param session:当前 pytest 会话对象
    :param config:当前的配置对象
    :param items:包含所有已收集测试项的列表
    :return:
    """
    print("Modifying collected items...")
    print(items)
    for i in items:
        print(i.name)

当我们使用 pytest .\test_demo.py 命令行启动我们测试的时候,我们可以看到如下打印: 

=========================================================================  test session starts ==========================================================================
platform win32 -- Python 3.10.5, pytest-8.3.1, pluggy-1.5.0
rootdir: C:\Users\w\Plants\pytest_demo
collecting ... Modifying collected items...
[<Function test_one>, <Function test_two>, <Function test_three>]
test_one
test_two
test_three
collected 3 items                                                                                                                                                        

test_demo.py F..                                                                                                                                                  [100%]

=============================================================================== FAILURES =============================================================================== 
_______________________________________________________________________________ test_one _______________________________________________________________________________ 

    def test_one():
        a = 100
>       assert a < 100
E       assert 100 < 100

test_demo.py:3: AssertionError
======================================================================= short test summary info ======================================================================== 
FAILED test_demo.py::test_one - assert 100 < 100
===================================================================== 1 failed, 2 passed in 0.04s ====================================================================== 

我们可以直接看到在test session starts 之后这里直接触发了我们的Modifying collected items...,证明在测试执行直接,会直接触发这个钩子函数,我们打印的参数

items:[<Function test_one>, <Function test_two>, <Function test_three>] 打印出来所有收集到的函数,然后直接将函数全部放到一个列表中

我们用for循环去一个个循环打印,会发现,这些函数其实是能点出来函数名的,

test_one,test_two,test_three按照收集的顺序打印出来,他执行也是这个列表的顺序

那么我们就可以在这个里面进行一些操作

改变收集到的测试case,去掉某些case执行:
def pytest_collection_modifyitems(session, config, items):
    """
    :param session:当前 pytest 会话对象
    :param config:当前的配置对象
    :param items:包含所有已收集测试项的列表
    :return:
    """
    print("Modifying collected items...")
    print(items)
    new_items = []
    for i in items:
        if i.name != 'test_one':
            new_items.append(i)
    print('select case list is {}'.format(new_items))
    items[:] = new_items


在这个代码中,我们将收集的case内容发生了改变,这样就会执行我们想要执行的特定case

 C:\Users\w\Plants\pytest_demo> pytest .\test_demo.py
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.10.5, pytest-8.3.1, pluggy-1.5.0
rootdir: C:\Users\w\Plants\pytest_demo
collecting ... Modifying collected items...
[<Function test_one>, <Function test_two>, <Function test_three>]
select case list is [<Function test_two>, <Function test_three>]
collected 3 items                                                                                                                                                        

test_demo.py ..                                                                                                                                                   [100%] 

========================================================================== 2 passed in 0.01s =========================================================================== 

在上面命令输出中,我们可以明显的看到,自动收集到的是3个case,但是因为我们中间做出了改变,最后实际执行的只有2个case,这两个才是我们真正想要执行的

在我们实际项目中,会存在case的自由组合执行,那么这个时候可能平台下发的case列表就可以做这样的操作,如下,我的case列表是最终写入在了一个json文件中,那么可以做这样的更改

test_case.json

{
  "test_case_list": [
    "test_one",
    "test_three"
  ]
}

那么在我的钩子函数中,我进行这样的修改:

def pytest_collection_modifyitems(session, config, items):
    """
    :param session:当前 pytest 会话对象
    :param config:当前的配置对象
    :param items:包含所有已收集测试项的列表
    :return:
    """
    print("Modifying collected items...")
    with open(r'test_case.json', 'r', encoding='utf8') as f:
        test_case_dict = json.load(f)
    test_case_list = test_case_dict['test_case_list']
    new_items = [item for item in items if item.name in test_case_list]
    print('select case list is {}'.format(new_items))
    items[:] = new_items

现在执行的打印就变成了

pytest .\test_demo.py -v 
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.10.5, pytest-8.3.1, pluggy-1.5.0 -- D:\Virtualenvs\Plants\Scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\w\Plants\pytest_demo
collecting ... Modifying collected items...
select case list is [<Function test_one>, <Function test_three>]
collected 3 items                                                                                                                                                        

test_demo.py::test_one FAILED                                                                                                                                     [ 50%]
test_demo.py::test_three PASSED                                                                                                                                   [100%] 

=============================================================================== FAILURES =============================================================================== 
_______________________________________________________________________________ test_one _______________________________________________________________________________ 

    def test_one():
        a = 100
>       assert a < 100
E       assert 100 < 100

test_demo.py:3: AssertionError
======================================================================= short test summary info ======================================================================== 
FAILED test_demo.py::test_one - assert 100 < 100
===================================================================== 1 failed, 1 passed in 0.03s ====================================================================== 

我们可以看到收集的还是3个case,但是我们直接用json文件中的test_case_list的case,这样最终执行的其实是我们想要执行的test_one跟test_three,这样就可以动态去改变执行case,实现从平台下发的case自由组合

其他钩子函数

暂时还没有实际用到,记录一下:

  1. pytest_configure(config):

    • 当 pytest 开始执行时调用。
    • 允许插件或者配置文件在整个测试运行之前执行一些初始化操作。
  2. pytest_unconfigure(config):

    • 当 pytest 执行完成后调用。
    • 可以用于执行一些清理操作或者收尾工作。
  3. pytest_addoption(parser, pluginmanager):

    • 用于添加额外的命令行选项。
    • 允许插件向 pytest 添加自定义的命令行选项,以控制测试运行的行为。
  4. pytest_generate_tests(metafunc):

    • 在测试收集阶段动态生成测试参数。
    • 可以根据需要动态生成测试参数,例如从外部数据源加载测试数据并生成测试用例。
  5. pytest_runtest_setup(item):

    • 在每个测试用例执行 setup 阶段之前调用。
    • 允许执行一些预备操作或者设置步骤,例如创建临时资源或者初始化测试环境。
  6. pytest_runtest_call(item):

    • 在每个测试用例执行测试函数时调用。
    • 可以在这里实现对测试用例执行过程的监控或者记录。
  7. pytest_runtest_teardown(item):

    • 在每个测试用例执行 teardown 阶段之后调用。
    • 可以用于清理测试用例执行过程中创建的资源或者状态恢复。
  8. pytest_sessionfinish(session, exitstatus):

    • 在整个测试会话结束时调用。
    • 允许进行最终的报告生成、日志记录或者资源释放等操作。

 有个有意思的钩子函数:

def pytest_sessionfinish(session, exitstatus):
    """
    :param session: 当前测试会话对象
    :param exitstatus: 测试退出码
    :return:
    """
    print(exitstatus)


# 如果我们全部都执行成功了这exitstatus就是0
# 如果有FAILED 这个exitstatus 就是ExitCode.TESTS_FAILED 代表有执行失败的case

可以按照这个退出码来判断我们case是不是执行成功了,如果这个exitstatus不为0,那么就代表这次测试肯定是有失败的,那么我们之间按照这个给平台发送一个失败的通知,这样不会从日志中去判断获取了

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pytest是一个功能强大的Python测试框架,它允许开发者编写自定义钩子函数来扩展其功能。钩子函数是在不同的测试阶段执行的函数,可以用于执行特定操作、修改测试运行环境或生成测试报告等。 下面是一些常见的pytest自定义钩子函数: 1. pytest_configure(config): 在pytest的配置阶段调用,可以在此函数中进行全局的配置设置。例如,添加自定义命令行选项或设置全局的测试环境。 2. pytest_sessionstart(session): 在整个测试会话开始之前调用,可以在此函数中执行一些初始化操作。 3. pytest_sessionfinish(session, exitstatus): 在整个测试会话结束之后调用,可以在此函数中执行一些清理操作或生成测试报告。 4. pytest_collection_modifyitems(config, items): 在收集到测试用例之后,但在执行测试用例之前调用。可以在此函数中修改或重新排序收集到的测试用例。 5. pytest_runtest_protocol(item, nextitem): 在每个测试用例执行之前和之后调用。可以在此函数中执行一些前置和后置操作,如准备测试数据、清理测试环境等。 6. pytest_runtest_setup(item): 在每个测试用例的setup阶段调用,可以在此函数中执行一些针对测试用例的前置操作。 7. pytest_runtest_call(item): 在每个测试用例的执行阶段调用,可以在此函数中执行测试用例的实际代码。 8. pytest_runtest_teardown(item, nextitem): 在每个测试用例的teardown阶段调用,可以在此函数中执行一些针对测试用例的后置操作。 通过编写这些自定义钩子函数,你可以实现各种定制化的操作,以满足特定的测试需求。你可以在pytest的文档中查找更多关于自定义钩子函数的详细信息和示例代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值