当执行 pytest 命令时,pytest 会从 project 中查找 test 来执行。本文先从几个路径相关的概念讲起,这样便于理解 pytest 在遍历路径时的走向。
定义了 Python 标准库的路径。
定义了 Python import 模块搜索的路径。
①如果是 module,目录中不包括__init__.py
,basedir 的值等于 a
a
|--b_test.py
②如果是 package,目录中包括__init__.py
,basedir 的值等于 y
y
|--a
| |--b_test.py
| |--__init__.py // 表明a是package
③如果是 package 的 package,目录中都包括__init__.py
,basedir 的值等于 x
x
|--y
| |--a
| |--__init__.py // 表明y是package
| | |--b_test.py
| | |--__init__.py // 表明a是package
模块搜索路径集,包括以上 3 个目录。它决定了 import 能否找到模块。
当前工作目录,缩写 cwd,等于执行pytest
命令的目录。
如果用python -m pytest
,以模块的方式来执行,会把 cwd 也加入 sys.path 中。
例如,在 a 目录下执行 pytest,cwd 是 a,basedir 是 y,sys.path 中只包含 y。如果执行 python -m pytest,sys.path 中既包含 y 也包含 a
y
|--a
| |--b_test.py
| |--__init__.py // 表明a是package
pytest 命令是可以加参数的,如果加了文件夹/文件参数,那么就只在参数指定的文件夹/文件中查找,可以指定多个。例如
pytest a_dir b_dir c_test.py d_test.py
特殊的,如果 a_dir 中包含了 c_test.py,那么会收集成 2 次,pytest 也会执行 2 次。
也可以使用::来指定函数/类/方法,例如
pytest test_mod.py::test_func
pytest test_mod.py::TestClass::test_method
pytest 不带参数。
从 “当前工作目录” 开始找,递归查找子目录。匹配 test_*.py 或 *_test.py 的文件。
找到这些模块(Python 中 1 个.py 文件就是 1 个模块)以后,进一步根据上节所述找 basedir。
调用sys.path.insert(0, basedir)
,把 basedir 加入 sys.path 中。这些模块就可以被 pytest import 了。
import 之后,查找 test 开头的函数或方法。如果是类中的方法,类必须以 Test 开头,并且没有__init__方法。
如果你觉得这篇文章写的还不错的话,关注公众号 “测试老树”,你的支持就是我写文章的最大动力。