先交代一下背景, 最近写代码, 想重构总是担心那里改坏了, 或者把依赖,导入等玩坏了, 但又没法检测. 面对自己之前的稀烂代码无可奈何, 痛下决心研究一下pytest. 目前已经够基本使用.
1. 为啥要写测试?
方便大胆的重构, 不用担心移动或者修改一段代码而导致一个模块或者整个系统出现问题.
方便检测代码bug. 自动化测试, 检测代码是否能如期实现自己想要的效果.
2. 为什么使用pytest?
TODO
3. pytest的官方页面和github地址
https://docs.pytest.org/en/latest/getting-started.html
https://github.com/pytest-dev/pytest
4. 安装
pip install pytest;
针对flask框架优化: pip install pytest-flask
5.测试代码结构
把测试代码放在你实际的应用代码以外. 如果你有很多功能的测试, 或者因为某些其他原因, 需要把测试代码和应用代码分离, 这么做是一个非常好的主意.
例如, 在项目根目录下
tests
├── conftest.py
├── fixtures.py
├── init.py
└── test_XXX.py
└── test_YYY_Dir
6. 每个文件的介绍.
fixtures.py里放置固件. 也就是由 @pytest.fixtures 装饰的函数.
conftest.py里放置测试的环境上下文变量. 也就是说测试需要使用到的变量, 固件都引入到这个文件里.
init.py 告诉pytest这是一个package. 这个文件夹是一个整体. 相当是一个模块, 也就是一个文件一样.
test__XXX.py 是你自己的测试代码
test_YYY_Dir 是你自己的测试代码目录, 在一个文件放置不合适的时候, 把这段代码组织成一个package.
7. pytest的自动检测机制.
参考
https://docs.pytest.org/en/latest/goodpractices.html#test-discovery
首先, pytest指定了特定的测试代码的组织方式和代码文件命名方式. 我们要做的就是遵守pytest的规范.
pytest 会运行 所有 当前目录和子目录下的test_.py和_test.py格式的文件.
如果没有指定参数, 那么 收集测试的工作,从testpaths 开始( 如果配置了testpaths的话 ), 否则从当前目录开始.
相应的, 命令行参数可以使用 任何目录的组合, 文件名字, 或者节点.
遍历进入目录, 除非有某些目录符合 非遍历目录 格式.
进入那些目录后, 搜索 test_.py或者_test.py文件, 被 当前测试包 导入(这里翻译比较拗口, 建议参考原版文档, 里面有详细解释, 但是这里不做翻译, 避免进入进入更深层次的文档. 参见https://docs.pytest.org/en/latest/goodpractices.html#test-package-name).
从这些文件里, 收集一下这些项:
类外面的 test_前缀的函数或者方法.
以Test为前缀的类里的 以test_为前缀的函数. 这个类里, 不能有__init__方法.
在python模块里, pytest还会检测那些使用标准 unittest.TestCase 类的测试. 也就是说 Pytest 兼容很多别的测试框架.
需要注意的事, 你的测试文件名字必须保持唯一. 以为pytest将会把他们作为顶级模块导入, 因为没有包去包裹他们.
如果你有同名的模块, 你需要给你的测试目录及其子目录里加上__init__.py, 把他们变成包. ( 没有__init__.py, 会直接把子目录里的文件也作为 顶级模块 导入, 到时候名字就会冲突.
8 .pytest如何启动一段测试代码?
pytest用python开发. 启动的方法很多. 可以使用命令行启动,当然 如果你用pycharm, 图形化界面启动也很方便. 缺点是图形化界面没有命令行那么自由, 优点是, 启动方便, 测试报告方便查看.
可以使用命令行启动, 使用命令行的命令也有好几种.
最常用的是 pytest test_file_path 跟上各种参数.
详细的参数含义, 可以自己使用 pytest --help 查看各个参数的意思.
如何使用pycharm启动测试文件呢?
右键选择一个测试文件, 选择 run py.test in FILENAME . 如果想debug的话, 也非常方便, 先给代码打上断点, 然后右键选择文件 debug py.test in FILENAME.
9. pytest的可选测试范围.
最大范围: 根目录下的全部测试代码. pytest tests/
某一个文件: pytest tests/file/path.py
某一个文件夹: pytest test/dir/
某一个测试类 pytest test/path/file.py::ClassName
某一个测试方法. pytest test/path/file.py::ClassName::FunctionName
10. 固件. fixture
测试函数可以接受fixture, 方式是把他们设置为输入参数, 对于每个参数名, 同名的固件函数会提供这个固件对象.
固件函数通过@pytest.fixture进行标记.
固件, 是pytest 最重要的概念之一. 详情请参考官方文档. https://docs.pytest.org/en/latest/fixture.html
今天先写这么多. 写文档可真是一件很累的事情.