注册
登录
从 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() # 返回退出状态 return session.exitstatus # pytest/collect.py def perform_collect(session, collector): # 收集测试文件和测试函数 items = [] for item in collector.collect(): items.append(item) return items # pytest/runner.py def runtest_protocol(item, nextitem): # 执行测试项 report = item.runtest() if report is None: # 处理异常情况 report = item.makereport() # 处理测试报告 item.session._hookmanager.hook.pytest_runtest_logreport(report=report)