首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

pytest的内置插件盘点16. recwarn

本文系《pytest源码剖析》系列内容

16. recwarn

插件路径:_pytest.recwarn

实现的 hook

调用的 hook

定义的 fixture

recwarn

插件功能

创建警告记录类:WarningsRecorder

创建警告验证类:WarningsChecker

创建 fixture:recwarn

记录警告内容

创建函数:deprecated_call

断言:引发了弃用警告

创建函数:warns

断言:引发了指定类型警告

代码片段

@fixturedef recwarn() -> Generator["WarningsRecorder", None, None]: wrec = WarningsRecorder(_ispytest=True) with wrec: warnings.simplefilter("default") yield wrec

def deprecated_call( # noqa: F811 func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any) -> Union["WarningsRecorder", Any]:

if func is not None: args = (func,) + args return warns((DeprecationWarning, PendingDeprecationWarning), *args, **kwargs)

def warns( # noqa: F811 expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, *args: Any, match: Optional[Union[str, Pattern[str]]] = None, **kwargs: Any,) -> Union["WarningsChecker", Any]: ... with WarningsChecker(expected_warning, _ispytest=True): return func(*args[1:], **kwargs)

fixturerecwarn返回了警告记录器

函数deprecated_call调用了warns

函数warns使用了警告验证器

如何断言警告

0. python 如何发出警告

def call_user_warning(): warnings.warn("这是一条用户警告", UserWarning) return 1

def call_deprecation_warning(): warnings.warn("这是一条弃用警告", DeprecationWarning) return 1

def call_syntax_warning(): warnings.warn("这是一条语法警告", SyntaxWarning) return 1

1. 断言出现警告

在 pytest 中,断言警告不是通过assert,而是pytest.warns

def test_has_warning_pass(): with pytest.warns(): # 出现警告则测试通过 call_user_warning()

def test_has_warning_fail(): with pytest.warns(): # 未出现警告失败 pass

2. 断言出现指定警告

def test_is_user_waring(): with pytest.warns(UserWarning): # 出现指定类型警告则通过 call_user_warning()

@pytest.mark.xfaildef test_is_user_waring_but_message_not_match(): with pytest.warns(UserWarning, match=r'hahahhaha \d+$'): # 出现指定警告,但内容不匹配 call_user_warning()

@pytest.mark.xfaildef test_is_not_user_waring(): with pytest.warns(SyntaxWarning): call_user_warning()

3. 获取警告内容,自定义断言

pytest.warns只能断言是否出现警告,

不能断言出现了几次警告

更不能对警告进行二次处理

获取警告内容之后,就可以进行更细致的断言了

def test_get_waring_message(recwarn): call_user_warning(3) # 引发警告 A call_syntax_warning() # 引发警告 B call_user_warning(6) # 引发警告 A

assert len(recwarn) == 3 # 断言警告数量

# 获取警告对象 warin_a = recwarn[0] warin_b = recwarn[1] warin_c = recwarn[2]

# 断言第一个警告对象 assert warin_a.category == UserWarning assert 'i=3' in str(warin_a.message) # 断言第二个警告对象 assert warin_b.category == SyntaxWarning assert '这是一条语法警告' == str(warin_b.message) # 断言第三个警告对象 assert warin_c.category == UserWarning assert 'i=6' in str(warin_c.message)

简评

pytest 中有 2 个和警告相关的插件:

recwarn(本插件):主要对内:记录警告,并进行断言

warings:主要对外,过滤或屏蔽代码引发的异常

warings插件,在本章节第 27 节进行梳理

...

WarningsRecorder和WarningsChecker的代码里充斥着大量的下划线、缩进,判断套判断、循环套循环

说实话,第一次看的时候非常头大

当理清楚之后才发现本插件代码 300 + 行,其中文档和注释将近一半以上,所以实际代码没多少

一共 2 个类 + 3 个函数,调用关系非常清晰。。。

这和我现在写《pytest 源码剖析》系列非常相似:

最开始的时候感觉非常难,无处下手的难

全凭给自己画饼,以未来巨大的成就感来鼓励和支持自己坚持下去

结果真做到之后,又感觉这其实没什么太大难度,

难以产生成就感,反倒有些茫然

  • 发表于:
  • 原文链接https://page.om.qq.com/page/Op5VHjldKaRgBPVv7vafRjGg0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券