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

pytest的内置插件盘点29. reports | 定义用例收集结果和执行结果对象

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

29. reports

插件路径:_pytest.reports

实现的 hook

调用的 hook

pytest_report_teststatus

定义的 fixture

插件功能

定义用例收集结果类CollectReport

定义用例执行结果类TestReport

实现结果的序列化、反序列化方法

代码片段

class TestReport(BaseReport):

def __init__( self, nodeid: str, location: Tuple[str, Optional[int], str], keywords: Mapping[str, Any], outcome: "Literal['passed', 'failed', 'skipped']", longrepr: Union[ None,TerminalRepr], when: "Literal['setup', 'call', 'teardown']", sections: Iterable[Tuple[str, str]] = (), duration: float = 0, user_properties: Optional[Iterable[Tuple[str, object]]] = None, **extra, ) -> None: pass class CollectReport(BaseReport):

when = "collect"

def __init__( self, nodeid: str, outcome: "Literal['passed', 'failed', 'skipped']", longrepr: Union[ None,TerminalRepr], result: Optional[List[Union[Item, Collector]]], sections: Iterable[Tuple[str, str]] = (), **extra, ) -> None:

TestReport 和 CollectReport 继承了相同的父类

CollectReport 比 TestReport 少了以下属性:

location

keywords

duration

user_properties

简评

虽然这个插件的名字叫 reports,但它并不是测试报告,而是测试报告的结果

此外,生成 HTML 报告的第三方插件比如:

pytest-html

allure-pytest

也是从 reports 插件中的 TestRepor 读取结果、生成报告的

...

这个插件实现了两个序列化相关的 hook,但是搜遍 pytest 源码,也没有发现在哪里调用过

于是推测在分布式场景下,用来传输测试结果的。

转手检索了 pytest-xdist 源码,果然证实了这个猜测

...

runner 收集测试用例时,会调用钩子 pytest_make_collect_report,将其返回值正是 CollectReport 对象

def pytest_make_collect_report(collector: Collector) -> CollectReport: call = CallInfo.from_call(lambda: list(collector.collect()), "collect") ... rep = CollectReport(collector.nodeid, outcome, longrepr, result) rep.call = call return rep

实例化对象时传递了 4 个参数,实例化之后,又赋值了 1 个属性,分别是:

call:用例收集的调用对象,包含返回值、异常信息、开始时间、结束时间、耗时

nodeid:收集对象的 id

outcome:收集状态

passed:没有异常信息

skipped:出现 skip 异常:

failed:出现其他异常

longrepr:skip 信息或异常信息,passed 没有信息

result:call 的返回值,可能是包、文件、类、用例本身

...

runner 执行测试用例时,会调用钩子 pytest_runtest_makereport,将其返回值正是 TestReport 对象

def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport: return TestReport.from_item_and_call(item, call)

调用 from_item_and_call 时传递了 2 个参数:

item:用例对象

call:用例执行的调用对象,包含返回值、异常信息、开始时间、结束时间、耗时

在 from_item_and_call 内会进行一系列的判断,构造合适的 TestReport 实例化参数

def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": ... return cls( item.nodeid, item.location, keywords, outcome, longrepr, when, sections, duration, user_properties=item.user_properties, )

其中:

item.nodeid:用例 id (唯一标识符)

item.location:用例位置(文件路径、行号、用例名)

keywords:用例关键字(目录名、文件名、用例名等)

outcome:执行状态(passed、failed、skipped 等)

longrepr:skip 信息或异常信息,passed 没有信息

when:执行阶段(setup、call、teardown)

sections:item._report_sections 中的信息

duration:执行耗时

user_properties:通过插件 junitxml 附加的信息

...

总结一下:

在pytest中runner 插件制作结果,reports 插件存储结果,tearminal 插件展示结果

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com