4. 车载自动化测试平台架构
Pytest 这东西,说白了就是 Python 测试界的瑞士军刀。我最早用 unittest 写测试时,每次都要写一堆 setUp、tearDown,烦得很。后来换了 Pytest,感觉整个世界都清爽了。这一章咱们就把 Pytest 的安装、配置、断言、规范、运行和报告生成,一次性讲透。
4.1 安装与配置
安装 Pytest 非常简单。我个人习惯用 pip 直接装:
pip install pytest
如果你需要生成 HTML 报告,再加一个插件:
pip install pytest-html
装完之后,验证一下是否成功:
pytest --version
嗯,这里要注意。如果你用的是虚拟环境,记得先激活环境再装。我曾经在一个项目里忘了激活虚拟环境,结果装到了全局 Python 里,折腾了半天才发现。
Pytest 的配置主要通过 pytest.ini 或 pyproject.toml 文件。我个人更推荐 pytest.ini,因为它更直观。举个例子:
[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v --tb=short
这个配置告诉 Pytest:去 tests 目录下找测试文件,文件名以 test_ 开头,类名以 Test 开头,函数名以 test_ 开头。运行的时候加 -v 显示详细信息,--tb=short 让错误信息更简洁。
pyproject.toml 里,跨平台兼容性更好。
4.2 断言机制
Pytest 的断言,说白了就是用 Python 原生的 assert 关键字。你想想看,这比 unittest 的 self.assertEqual() 简洁多了吧?
基本用法:
def test_addition():
result = 1 + 1
assert result == 2
def test_string():
name = "pytest"
assert "py" in name
assert len(name) > 0
def test_list():
items = [1, 2, 3]
assert 2 in items
assert len(items) == 3
为什么 Pytest 的断言这么强大?因为它会在断言失败时,自动显示上下文信息。比如:
def test_failure():
a = 10
b = 20
assert a == b
运行后你会看到类似这样的输出:
E assert 10 == 20
E + where 10 = a
E + and 20 = b
你看,它直接告诉你 a 是 10,b 是 20,一目了然。我在项目中遇到过很多新手,断言失败后一脸懵,不知道变量值是什么。用 Pytest 就没这问题。
常用的断言场景:
| 场景 | 断言写法 | 说明 |
|---|---|---|
| 相等 | assert a == b |
判断两个值相等 |
| 不相等 | assert a != b |
判断两个值不相等 |
| 包含 | assert x in y |
判断 x 是否在 y 中 |
| 不包含 | assert x not in y |
判断 x 是否不在 y 中 |
| 真值 | assert x |
判断 x 是否为 True |
| 假值 | assert not x |
判断 x 是否为 False |
| 近似相等 | assert abs(a - b) < 0.001 |
浮点数比较时用 |
assert a == b。我曾经在测试一个计算价格的函数时,就因为浮点数精度问题,导致测试时好时坏。后来改用 assert abs(a - b) < 0.001 才稳定下来。
4.3 测试用例编写规范
Pytest 的测试用例编写,有几个硬性规则。说白了,就是约定大于配置:
- 文件名: 以
test_开头,比如test_login.py - 类名: 以
Test开头,比如TestLogin - 函数名: 以
test_开头,比如test_login_success
一个完整的测试用例示例:
# test_calculator.py
class TestCalculator:
def test_addition(self):
assert 1 + 1 == 2
def test_subtraction(self):
assert 5 - 3 == 2
def test_multiplication(self):
assert 3 * 4 == 12
def test_division(self):
assert 10 / 2 == 5
我个人习惯把测试用例按功能模块分组。比如用户模块的测试放 test_user.py,订单模块的测试放 test_order.py。这样找起来方便,维护也简单。
测试用例的命名也很重要。我建议用 test_功能_场景_预期结果 的格式。比如:
test_login_valid_user_should_succeedtest_login_invalid_password_should_failtest_login_empty_username_should_show_error
你想想看,如果测试失败了,光看名字就知道是哪个场景出了问题,多省事。
assert,最多不超过三个。
4.4 运行与报告生成
运行测试用例,最基础的方式就是在终端里敲:
pytest
Pytest 会自动发现当前目录及子目录下所有符合规范的测试文件并执行。如果你想指定某个文件:
pytest tests/test_login.py
常用的运行参数:
| 参数 | 作用 | 示例 |
|---|---|---|
-v |
显示详细信息 | pytest -v |
-s |
显示 print 输出 | pytest -s |
-k |
按关键字筛选用例 | pytest -k "login" |
-x |
遇到第一个失败就停止 | pytest -x |
--maxfail=n |
失败 n 次后停止 | pytest --maxfail=2 |
--tb=short |
缩短错误信息 | pytest --tb=short |
生成 HTML 报告,需要用到 pytest-html 插件:
pytest --html=report.html
运行完后,当前目录下会生成一个 report.html 文件。打开它,你会看到所有测试用例的执行结果、耗时、错误信息等。我在项目中经常用这个报告给团队看,比在终端里翻日志方便多了。
如果你想在报告中包含截图或自定义内容,可以这样:
pytest --html=report.html --self-contained-html
--self-contained-html 参数会把所有资源(CSS、JS)都打包进一个 HTML 文件里,方便分享。
--junitxml=report.xml 参数,生成 JUnit 格式的 XML 报告。这样 Jenkins、GitLab CI 等工具可以直接解析,展示测试结果。
4.5 知识结构总览
这一章的内容比较多,我画了一张图帮你梳理一下整体脉络:
这张图把 Pytest 的四个核心模块串起来了。从安装配置开始,到断言机制、编写规范,最后是运行和报告生成。你跟着这个脉络走,就不会乱。
4.6 实战小练习
光看不练假把式。我建议你现在就动手:
- 创建一个
test_demo.py文件 - 写三个测试函数:一个测试字符串拼接,一个测试列表排序,一个测试字典取值
- 运行
pytest -v查看结果 - 生成 HTML 报告:
pytest --html=report.html
做完这些,Pytest 的基础操作你就基本掌握了。嗯,就是这么简单。