Why pytest ?
评价单元测试是否优秀,分支覆盖率是非常重要的指标,而覆盖率的决定因素除了开发自身的素质以外,足够低的用例构建成本也是必不可少。
对于 Python 应用,当项目逻辑复杂度较高时,单纯使用原生的 unittest
或者是 Django 提供的 TestCase
都会遇到一个恼人的问题:测试代码大部分工作在构建各种用例。幸好有 pytest
提供的 fixture
机制,可以较好的解决这个问题。
本文简单阐述个人的 pytest 使用实践,而关于 fixture
到底好在哪里或者具体使用方法,已经有比较多的文章做了更详细的介绍,我这里就不再赘述:
- https://blog.daftcode.pl/the-cleaning-hand-of-pytest-28f434f4b684
- https://salmonmode.github.io/2019/03/29/building-good-tests.html#dont-inherit-from-unittesttestcase-in-test-classes-either-directly-or-indirectly
理想的单元测试
从理论来讲,对于一个测试项,我们应该只需关心测试内容的输入和输出(或异常),并且最好能够放到一起管理维护,更形象地说,应该是下面这种伪代码的感觉
1 | (输入, 预期输出) |
一个普通的 pytest
使用用例:
1 |
|
可以看出 pytest.fixture
固然能够足够强大,但是并不能完全解决问题:因为 fixture
在这里的用法是 静态 的,而对于我们理想的状态,用例中的输入输出,都应该是动态指定的。
一个简单的实践
所以,我们需要利用 fixture factory
来实现
1 | # fixture 依旧保留了复用性 |
这样一来,只要我在一开始构建好相关的工厂函数,添加更多的测试用例就只需在 parametrize
中不断添加即可,开发注意力成功从重复的工具构建转移到了真实用例。