pytest架构是什么?
首先,来看一个 pytest 的例子:
def test_a():
print(123)
collected 1 item
test_a.py . [100%]
============ 1 passed in 0.02s =======================
输出结果很简单:收集到 1 个用例,并且这条测试用例执行通过。
此时思考两个问题:
1.pytest 如何收集到用例的?
2.pytest 如何把 python 代码,转换成 pytest 测试用例(又称 item) ?
pytest如何做到收集到用例的?
这个很简单,遍历执行目录,如果发现目录的模块中存在符合“ pytest 测试用例要求的 python 对象”,就将之转换为 pytest 测试用例。
比如编写以下 hook 函数:
def pytest_collect_file(path, parent):
print("hello", path)
hello C:\Users\yuruo\Desktop\tmp\tmp123\tmp\testcase\__init__.py
hello C:\Users\yuruo\Desktop\tmp\tmp123\tmp\testcase\conftest.py
hello C:\Users\yuruo\Desktop\tmp\tmp123\tmp\testcase\test_a.py
会看到所有文件内容。
pytest 像是包装盒,将 python 对象包裹起来,比如下图:
当写好 python 代码时:
def test_a:
print(123)
会被包裹成 Function :
<Function test_a>
可以从 hook 函数中查看细节:
def pytest_collection_modifyitems(session, config, items):
pass
于是,理解包裹过程就是解开迷题的关键。pytest 是如何包裹 python 对象的?
下面代码只有两行,看似简单,但暗藏玄机!
def test_a:
print(123)
把代码位置截个图,如下:
我们可以说,上述代码是处于“testcase包”下的 “test_a.py模块”的“test_a函数”, pytest 生成的测试用例也要有这些信息:
处于“testcase包”下的 “test_a.py模块”的“test_a测试用例:
把上述表达转换成下图:
pytest 使用 parent 属性表示上图层级关系,比如 Module 是 Functi