Pytest权威教程-20编写钩子(hooks)方法函数

编写钩子(hooks)方法函数

钩子(hooks)方法函数验证和执行

pytest为任何给定的钩子(hooks)方法规范调用已注册插件的钩子(hooks)方法函数。让我们看一下钩子(hooks)方法的典型钩子(hooks)方法函数,pytest在收集完所有测试项目后调用。pytest_collection_modifyitems(session,config,items)

当我们pytest_collection_modifyitems在插件中实现一个函数时,pytest将在注册期间验证你是否使用了与规范匹配的参数名称,如果没有则拯救。

让我们看一下可能的实现:

def pytest_collection_modifyitems(config,items):
    # called after collection is completed
    # you can modify the ``items`` list
    ...

这里,pytest将传入config(pytest配置对象)和items(收集的测试项列表),但不会传入session参数,因为我们没有在函数签名中列出它。这种动态的“修剪”参数允许pytest“未来兼容”:我们可以引入新的钩子(hooks)方法命名参数而不破坏现有钩子(hooks)方法实现的签名。这是pytest插件的一般长期兼容性的原因之一。

请注意,除了pytest_runtest_*不允许引发异常之外的钩子(hooks)方法函数。这样做会打破pytest运行。

firstresult:首先停止非无结果

大多数对pytest钩子(hooks)方法的调用都会产生一个结果列表,其中包含被调用钩子(hooks)方法函数的所有非None结果。

一些钩子(hooks)方法规范使用该firstresult=True选项,以便钩子(hooks)方法调用仅执行,直到N个注册函数中的第一个返回非None结果,然后将其作为整个钩子(hooks)方法调用的结果。在这种情况下,不会调用其余的钩子(hooks)方法函数。

hookwrapper:在其他钩子(hooks)方法周围执行

版本2.7中的新函数。

pytest插件可以实现钩子(hooks)方法包装器,它包装其他钩子(hooks)方法实现的执行。钩子(hooks)方法包装器是一个生成器函数,它只产生一次。当pytest调用钩子(hooks)方法时,它首先执行钩子(hooks)方法包装器并传递与常规钩子(hooks)方法相同的参数。

在钩子(hooks)方法包装器的屈服点,pytest将执行下一个钩子(hooks)方法实现,并以Result封装结果或异常信息的实例的形式将其结果返回到屈服点。因此,屈服点本身通常不会引发异常(除非存在错误)。

以下是钩子(hooks)方法包装器的示例定义:

import pytest

@pytest.hookimpl(hookwrapper=True)
def pytest_pyfunc_call(pyfuncitem):
    do_something_before_next_hook_executes()

    outcome = yield
    # outcome.excinfo may be None or a (cls,val,tb) tuple

    res = outcome.get_result()  # will raise if outcome was exception

    post_process_result(res)

    outcome.force_result(new_res)  # to override the return value to the plugin system

请注意,钩子(hooks)方法包装器本身不返回结果,它们只是围绕实际的钩子(hooks)方法实现执行跟踪或其他副作用。如果底层钩子(hooks)方法的结果是一个可变对象,它们可能会修改该结果,但最好避免它。

有关更多信息,请参阅插件文档

钩子(hooks)方法函数排序/调用示例

对于任何给定的钩子(hooks)方法规范,可能存在多个实现,因此我们通常将hook执行视为1:N函数调用,其中N是已注册函数的数量。有一些方法可以影响钩子(hooks)方法实现是在其他人之前还是之后,即在N-sized函数列表中的位置:

# Plugin 1
@pytest.hookimpl(tryfirst=True)
def pytest_collection_modifyitems(items):
    # will execute as early as possible
    ...

# Plugin 2
@pytest.hookimpl(trylast=True)
def pytest_collection_modifyitems(items):
    # will execute as late as possible
    ...

# Plugin 3
@pytest.hookimpl(hookwrapper=True)
def pytest_collection_modifyitems(items):
    # will execute even before the tryfirst one above!
    outcome = yield
    # will execute after all non-hookwrappers executed

这是执行的顺序:

  1. Plugin3的pytest_collection_modifyitems被调用直到屈服点,因为它是一个钩子(hooks)方法包装器。
  2. 调用Plugin1的pytest_collection_modifyitems是因为它标有tryfirst=True
  3. 调用Plugin2的pytest_collection_modifyitems因为它被标记`trylast=True(但即使没有这个标记,它也会在Plugin1之后出现)。
  4. 插件3的pytest_collection_modifyitems然后在屈服点之后执行代码。yield接收一个Result实例,该实例封装了调用非包装器的结果。包装不得修改结果。

这是可能的使用tryfirst,并trylast结合还hookwrapper=True处于这种情况下,它会影响彼此之间hookwrappers的排序。

声明新钩子(hooks)方法

插件和conftest.py文件可以声明新钩子(hooks)方法,然后可以由其他插件实现,以便改变行为或与新插件交互:

在插件注册时调用,允许通过调用添加新的挂钩。pluginmanager.add_hookspecs(module_or_class,prefix)
参数: pluginmanager(*_pytest.config.PytestPluginManager*) - pytest插件管理器

注意:
这个钩子(hooks)方法与之不相容hookwrapper=True

钩子(hooks)方法通常被声明为do-nothing函数,它们只包含描述何时调用钩子(hooks)方法以及期望返回值的文档。

有关示例,请参阅[xdist中。

可选择使用第三方插件的钩子(hooks)方法

由于标准的[验证机制,方法可能有点棘手:如果你依赖未安装的插件,验证将失败并且错误消息对你的用户没有多大意义。

一种方法是将钩子(hooks)方法实现推迟到新的插件,而不是直接在插件模块中声明钩子(hooks)方法函数,例如:

# contents of myplugin.py

class DeferPlugin(object):
    """Simple plugin to defer pytest-xdist hook functions."""

    def pytest_testnodedown(self,node,error):
        """standard xdist hook function.
 """

def pytest_configure(config):
    if config.pluginmanager.hasplugin("xdist"):
        config.pluginmanager.register(DeferPlugin())

这具有额外的好处,允许你根据安装的插件有条件地安装挂钩。

转载于:https://www.cnblogs.com/superhin/p/11478007.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值