从pytest源码的角度分析pytest工作原理
从pytest源码的角度分析pytest工作原理
从
pytest
源代码的角度来分析其工作原理,我们需要关注几个关键的部分,特别是
pytest
的启动过程以及测试的收集与执行。下面是基于
pytest
源代码的一个高层次的概述。
pytest 的启动过程
命令行解析:
pytest
的入口点是
conftest.py
文件中的
pytest.main()
函数。- 在这个函数中,首先通过
pytest.config.get_config()
获取配置。 - 接着使用
pytest.config.parse()
来解析命令行参数。
配置加载:
pytest
会在当前目录及其父目录递归地查找配置文件,比如
pytest.ini
或
pyproject.toml
。- 使用
pytest.config.Config
类来存储配置信息。
插件管理:
- 通过
pytest.hookspec
和
pytest.pluginmanager
来管理插件。 - 插件可以在各个阶段被注册并调用。
- 通过
测试收集过程
收集器初始化:
pytest
使用
pytest.collect
模块来处理测试收集。Session.from_parent
方法创建一个新的
Session
实例。Collector.from_parent
方法用于构建收集器树。
测试文件发现:
pytest
通过
Session.perform_collect
方法来遍历目录结构并发现测试模块。File.from_parent
方法用于创建
File
实例来代表测试文件。Function.from_parent
方法用于创建
Function
实例来代表测试函数。
测试项构建:
- 一旦发现了测试文件,就会通过
collect
方法来收集文件中的测试函数。 - 测试函数会被转换成
Item
实例。
- 一旦发现了测试文件,就会通过
测试执行过程
测试项准备:
- 在测试开始之前,会调用
Session.perform_setup
方法来进行一些预处理。 - 这个阶段可能包括设置环境变量、初始化数据库连接等。
- 在测试开始之前,会调用
测试项执行:
Session.runtestloop
方法控制测试项的实际执行。- 对于每一个
Item
实例,都会调用
Session.perform_test
方法来执行测试。
测试结果收集:
- 测试执行的结果会被收集并存储在
Item
实例中。 - 可能会触发
pytest_runtest_logreport
hook,该 hook 被用来处理测试报告。
- 测试执行的结果会被收集并存储在
异常处理:
- 如果测试过程中发生异常,
pytest
会捕获这些异常并记录下来。 - 异常可以通过
pytest_runtest_makereport
hook 来处理。
- 如果测试过程中发生异常,
测试报告生成
Session
实例负责收集所有的测试结果。Session.exitstatus
属性会根据测试结果来确定程序的退出状态码。pytest
可以生成多种格式的报告,这取决于安装的插件。
示例代码片段
下面是一些示例代码片段,展示了
pytest
源代码中的关键部分:
#pytest/conftest.py def main(args=None):#解析命令行参数 config =get_config(args)#加载插件 pm =PluginManager()
pm.load_setuptools_entrypoints('pytest11')#创建 Session 实例 session = Session.from_parent(config, plugins=pm)#执行测试 session.runtestloop()#返回退出状态 returnsession.exitstatus#pytest/collect.py defperform_collect(session, collector):#收集测试文件和测试函数 items =[]for item incollector.collect():
items.append(item)returnitems#pytest/runner.py defruntest_protocol(item, nextitem):#执行测试项 report =item.runtest()if report isNone:#处理异常情况 report =item.makereport()#处理测试报告 item.session._hookmanager.hook.pytest_runtest_logreport(report=report)