概述
编写钩子(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
这是执行的顺序:
- Plugin3的pytest_collection_modifyitems被调用直到屈服点,因为它是一个钩子(hooks)方法包装器。
- 调用Plugin1的pytest_collection_modifyitems是因为它标有
tryfirst=True
。 - 调用Plugin2的pytest_collection_modifyitems因为它被标记`trylast=True(但即使没有这个标记,它也会在Plugin1之后出现)。
- 插件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
最后
以上就是漂亮身影为你收集整理的Pytest权威教程-20编写钩子(hooks)方法函数的全部内容,希望文章能够帮你解决Pytest权威教程-20编写钩子(hooks)方法函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复