单元测试的概念可能多数读者都有接触过。作为开发人员,我们编写一个个测试用例,测试框架发现这些测试用例,将它们组装成测试 suite 并运行,收集测试报告,并且提供测试基础设施(断言、mock、setup 和 teardown 等)。Python 当中最主流的单元测试框架有三种,Pytest, nose 和 Unittest,其中 Unittest 是标准库,其它两种是第三方工具。在 ppw 向导生成的项目中,就使用了 Pytest 来驱动测试。
这里主要比较一下 pytest 和 unittest。多数情况下,当我们选择单元测试框架时,选择二者之一就好了。unitttest 基于类来组织测试用例,而 pytest 则是函数式的,基于模块来组织测试用例,同时它也提供了 group 概念来组织测试用例。pytest 的 mock 是基于第三方的 pytest-mock,而 pytest-mock 实际上只是对标准库中的 mock 的简单封装。单元测试都会有 setup 和 teardown 的概念,unittest 直接使用了 setUp 和 tearDown 作为测试入口和结束的 API,在 pytest 中,则是通过 fixture 来实现,这方面学习曲线可能稍微陡峭一点。在断言方面,pytest 使用 python 的关键字 assert 进行断言,比 unittest 更为简洁,不过断言类型上没有 unittest 丰富。
另外一个值得一提的区别是,unittest 从 python 3.8 起就内在地支持 asyncio,而在 pytest 中,则需要插件 pytest-asyncio 来支持。但两者在测试的兼容性上并没有大的不同。
pytest 的主要优势是有:
- pytest 的测试用例更简洁。由于测试用例并不是正式代码,开发者当然希望少花时间在这些代码上,因此代码的简洁程度很重要。
- 提供了命令行工具。如果我们仅使用 unittest,则执行单元测试必须要使用
python -m unittest来执行;而通过 pytest 来执行单元测试,我们只需要调用pytest .即可。 - pytest 提供了 marker,可以更方便地决定哪些用例执行或者不执行。
- pytest 提供了参数化测试。
这里我们简要地举例说明一下什么是参数化测试,以便读者理解为什么参数化测试是一个值得一提的优点。
# 示例 7 - 1
import pytest
from datetime import datetime
from src.example import get_time_of_day
@pytest.mark.parametrize(
"datetime_obj, expect",
[
(datetime(2016, 5, 20, 0, 0, 0), "Night"),
(datetime(2016, 5, 20, 1, 10, 0), "Night"),
(datetime(2016, 5, 20, 6, 10, 0), "Morning"),
(datetime(2016, 5, 20, 12, 0, 0), "Afternoon"),
(datetime(2016, 5, 20, 14, 10, 0), "Afternoon"),
(datetime(2016, 5, 20, 18, 0, 0), "Evening"),
(datetime(2016, 5, 20, 19, 10, 0), "Evening"),
],
)
def

本文比较了Python的主流单元测试框架pytest和unittest,强调了pytest的简洁性、命令行工具、参数化测试和mock功能,以及其在组织测试代码和异步支持方面的优势。
最低0.47元/天 解锁文章
1622

被折叠的 条评论
为什么被折叠?



