4. 搭建自动化测试环境:Python、pytest、unittest 归纳总结
要说搭建自动化测试环境,我这些年踩过的坑还真不少。刚开始的时候,我总觉得装个 Python、写几个测试用例就完事了。结果呢?项目一复杂,环境冲突、版本不兼容、测试框架选型失误……各种问题接踵而至。今天我们就来捋一捋,到底怎么把测试环境搭得干净、可靠、可维护。
4.1 Python 环境准备——别小看这一步
Python 版本管理是第一道坎。我见过团队因为某个人在服务器上直接装了 Python 3.12,结果依赖的 some old lib 跑不起来,排查了一整天。个人建议用 pyenv 或者 conda 来隔离版本。
.venv,然后 pip install -r requirements.txt。这样换机器也好,多人协作也好,不会乱。
举一个我最常用的初始化脚本:
# 创建虚拟环境
python -m venv .venv
# 激活(Windows)
.venv\Scripts\activate
# 激活(Mac/Linux)
source .venv/bin/activate
# 安装测试依赖
pip install pytest pytest-cov unittest-xml-reporting
有意思的是,很多人装了 pytest 后,unittest 自带的标准库就不管了。其实它俩可以共存,后面我会说怎么选。
4.2 pytest——我现在的首选
pytest 用起来是真爽。你想想看,不需要写繁琐的 TestCase 类,函数名带 test_ 开头就好了。自动发现测试文件,报错信息也清晰。
我记得刚接手一个老项目时,里面全是 unittest,参数化测试要写十几行 for 循环。我花了一个下午把核心模块改成 pytest 的 @pytest.mark.parametrize,代码量直接砍掉一半。嗯,这里要注意:pytest 可以原生运行 unittest.TestCase,迁移成本很低。
看一个简单的例子:
# test_sample.py
import pytest
def test_add():
assert 1 + 1 == 2
@pytest.mark.parametrize("a, b, expected", [
(1, 2, 3),
(3, 5, 8),
(-1, 1, 0)
])
def test_param(a, b, expected):
assert a + b == expected
跑一下 pytest -v,结果一目了然。
4.3 unittest——老牌稳定,但不是最优
unittest 是 Python 标准库,不用额外安装。对于中小型 SDK 回归测试,它完全够用。但语法偏啰嗦,你得写 class TestSomething(unittest.TestCase),里面方法名 test_xxx,断言用 self.assertEqual。
说实话,我现在只有两种场景会用它:
一是必须在不允许装第三方包的 CI 环境里跑测试;
二是我要验证一个遗留系统,里面全是 unittest 风格的测试,我懒得全改。
一个典型的 unittest 测试类:
import unittest
class TestMath(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 1, 2)
def test_sub(self):
self.assertEqual(2 - 1, 1)
if __name__ == '__main__':
unittest.main()
4.4 框架对比——一张表说清楚
很多新人问我到底选哪个。我把核心维度列出来,你看完就明白了。
| 对比维度 | pytest | unittest |
|---|---|---|
| 安装方式 | 需 pip install | 标准库自带 |
| 用例编写风格 | 函数式 + 装饰器 | 面向对象,类继承 |
| 参数化测试 | @pytest.mark.parametrize 原生支持 | 需自己写循环或用 subTest |
| fixture 机制 | 灵活,作用域可控 | setUp/tearDown,粒度有限 |
| 插件生态 | 非常丰富(pytest-cov, xdist 等) | 较少,扩展麻烦 |
| 报告可读性 | 详细,带颜色 diff | 朴素,需额外工具 |
| 运行老 unittest | 可兼容运行 | 原生运行 |
说白了,新项目我无脑选 pytest。老项目如果纯 unittest 且规模不大,我会保留它,但不推荐长时间混用。
4.5 环境搭建全流程——我推荐的步骤
下面是我自己在多个 SDK 回归测试项目中用熟的步骤,你照着走基本不会出错。
- 确定 Python 版本:看 SDK 官网要求,比如只支持 3.8–3.11,那就装对应版本。
- 创建虚拟环境:用
python -m venv .venv或conda create -n sdk_test python=3.10。 - 安装 pytes:
pip install pytest pytest-cov。 - 可选安装 unittest-xml-reporting:如果 CI 需要 JUnit 格式报告,这个库能把 unittest 结果输出成 XML。
- 编写 conftest.py:放在 tests 目录下,集中管理 fixture 和钩子。
- 运行一次全部测试:
pytest --cov=your_sdk,看看覆盖率,也验证环境通不通。
.venv 重新建一个,再 pip install -r requirements.txt。我吃过依赖版本锁定的亏,之后都加 pip freeze > requirements.txt 并在 PR 中更新。
4.6 整体知识结构图
下面这张图把三大块的关系梳理了一下。看看就好,心里有个全貌。
4.7 避坑清单——都是真金白银换来的
- 依赖版本锁定:一定要用
requirements.txt锁定版本,否则某天 pytest 升级了,你的 fixture 写法不兼容,哭都来不及。 - 不要全局安装:我吃过最亏的一次,直接在系统 Python 里
pip install,结果同一个包在两个项目里版本冲突,搞得我重装了系统环境。 - pytest 和 unittest 混用的目录结构:建议把 unittest 风格的测试单独放在
tests/unittests/下,pytest 放在tests/integration/,然后用pytest.ini配置testpaths,避免扫描混乱。 - CI 环境里不要装无关包:用
pip install -r requirements.txt --no-deps可以避免拉入不必要的依赖。 - Windows 上的编码问题:pytest 输出中文 log 时偶尔乱码,在
conftest.py里加上sys.stdout.reconfigure(encoding='utf-8')能搞定。
以上就是我总结的 Python + pytest + unittest 环境搭建经验。记住一句话:环境搭好了,后面写测试用例才真正顺手。别一开始贪快,后面补坑的代价更大。