altosadventure免费中文版
84.52M · 2025-09-11
pytest 的架构是围绕一棵节点树 (Node Tree) 构建的。这棵树在收集阶段 (Collection) 被创建,代表了整个测试会话的结构。
Config
对象作用:这是 pytest 的全局上下文和控制中心。它贯穿整个测试生命周期的始末,是所有配置信息、插件系统和共享数据的承载者。
关键属性和方法:
pluginmanager
: 最重要的属性之一,是 pluggy.PluginManager
的实例。所有钩子的调用都通过它进行 (config.hook.x()
实际上是 config.pluginmanager.hook.x()
)。
option
: 一个 argparse.Namespace
对象,存储了所有解析后的命令行参数(如 config.option.verbose
, config.option.collectonly
)。
_inicache
: 存储从 pytest.ini
、pyproject.toml
等配置文件解析出的内容。
rootpath
: 项目根目录的路径。
stash
: 一个字典类型的属性,用于在插件之间共享自定义数据,非常好用。例如,一个插件可以在 config.stash['my_cache'] = {}
中存储数据,另一个插件可以读取它。
hook
: 钩子调用器。所有对 pytest 钩子的调用都通过 config.hook.hook_name(...)
完成。
生命周期:在 pytest.main()
开始时创建,在整个会话结束时销毁。
Session
对象作用:根收集器 (Root Collector),代表一次完整的 pytest 测试会话。它是节点树的根,是所有其他节点(目录、文件、测试项)的父节点。
关键属性和方法:
items
: 这是一个极其重要的列表。在收集阶段结束后,它包含了所有将要被执行的测试项 (Item) 的列表。pytest_collection_modifyitems
钩子操作的就是这个列表。
config
: 指向全局的 Config
对象。
collect()
: 方法。开始收集过程,从当前会话(通常是命令行指定的开始路径)向下收集,构建整个节点树。
继承关系:Session
-> Node
-> Collector
Node
基类作用:所有其他组件(Session
, Collector
, Item
)的抽象基类。它定义了节点树中每个节点都具有的基本属性和方法。
关键属性和方法:
name
: 节点的短名称(如函数名 test_my_function
)。
nodeid
: 节点的唯一标识符,是它在节点树中的完整路径(如 test_file.py::TestClass::test_method
)。这是报告和过滤中使用的关键ID。
parent
: 指向父节点的引用(如一个 Module
节点的父节点是 Session
或 Directory
)。
config
: 指向全局的 Config
对象。
ihook
: 一个便捷属性,等价于 self.config.hook
,用于在当前节点调用钩子。
Collector
收集器作用:继承自 Node
。负责收集子节点。它们构成了节点树的枝干。
类型:
Session
: 根收集器。
Directory
: 代表一个目录,收集其下的 __init__.py
文件(如果被视为包)和其他子目录或 Python 文件。
File
: 通常具体化为 Module
,代表一个 Python 文件(如 test_sample.py
)。
关键方法:
collect()
: 核心方法。它被调用时,会返回一个子节点列表。这些子节点可以是更下层的 Collector
(如 Module
收集 Class
),也可以是最终的 Item
(如 Module
收集 Function
)。
python
def collect(self): collected_children = [] # ... 遍历自身范围内的对象(如模块的属性、类的属性)... for obj in found_objects: if is_test_class(obj): collected_children.append(Class.from_parent(parent=self, name=obj.name)) elif is_test_function(obj): collected_children.append(Function.from_parent(parent=self, name=obj.name)) return collected_children
Item
测试项作用:继承自 Node
。代表一个最小的、可执行的测试单元,是节点树的叶子。最常见的两种是 Function
(测试函数)和 UnitTestCase
( unittest 风格的测试方法)。
关键方法:
runtest()
: 核心方法。当执行阶段到来时,调用此方法会真正运行测试。对于 pytest.Function
,它内部会调用 pytest_pyfunc_call
钩子,从而执行被 @pytest.fixture
装饰的依赖项和测试函数本身。
funcargs
: 一个字典,在 setup
阶段后填充。键是测试函数参数的名称,值是对应的 fixture 返回值。item.runtest()
最终会执行 test_function(**item.funcargs)
。
生命周期:由 Collector
创建,由 pytest_runtest_protocol
执行。
Fixture
夹具系统作用:依赖注入系统,是 pytest 的核心功能。用于提供测试所需的数据、状态或环境设置/清理。
核心概念:
@pytest.fixture
装饰器:用于声明一个函数是 fixture。可以指定 scope
("function"
, "class"
, "module"
, "session"
), autouse
, params
(参数化)等。
request
对象:一个具有魔力的上下文参数,会自动传递给每个 fixture 函数。它提供了关于“谁请求了这个 fixture”的信息。
request.node
: 获取请求该 fixture 的 Item
或 Collector
节点。
request.function
: 获取请求该 fixture 的测试函数(如果是函数级)。
request.cls
: 获取请求该 fixture 的测试类。
request.module
: 获取请求该 fixture 的测试模块。
request.config
: 获取全局的 Config
对象。
request.addfinalizer(finalizer_func)
或 yield
: 用于定义 teardown 清理逻辑。
pytest.fixture
内部工作原理:
发现:当收集到一个 Item
时,pytest 会分析其参数列表。
匹配:对于每个参数名,去寻找同名的 fixture 函数。
排序:根据 fixture 的依赖关系和 scope 对它们进行排序。
缓存:为相同 scope 的请求缓存 fixture 实例。
执行 (Setup):在测试运行的 setup
阶段,按顺序执行 fixture 函数,获取返回值并存入 item.funcargs
。
注入:在 call
阶段,将 funcargs
解包并传入测试函数。
清理 (Teardown):在 teardown
阶段,执行通过 yield
或 addfinalizer
注册的清理函数。