上篇讲解 Pytest 类 & 方法级前后置 setup_class/setup_method,本篇聚焦测试核心:断言。自动化用例靠断言判定执行结果,Pytest 摒弃 unittest 繁琐断言方法,直接使用 Python 原生 assert,简洁高效,是接口、UI 自动化高频用法。
一、什么是断言?Pytest 选用原生 assert 的优势
断言用来校验程序实际结果与预期结果是否一致:条件为 True,用例通过;条件为 False,抛出 AssertionError,用例失败终止执行。
对比 unittest,Pytest assert 两大优点
- **语法极简:**不用记忆self.assertEqual、self.assertIn、self.assertTrue等一堆方法,直接用原生运算符==、>、in、is,降低学习成本。
- 报错详情自动解析 :Pytest 底层重写 assert,失败自动打印实际值、期望值、变量来源、数据差异,不用手动拼接日志排查问题。
unittest 冗余示例:
python
import unittest
class TestDemo(unittest.TestCase):
def test_01(self):
res = 2+3
self.assertEqual(res,6,"结果错误")
Pytest 简洁写法:
python
def test_01():
res = 2+3
assert res ==6, f"预期6,实际{res}"
二、assert 基础语法
python
assert 布尔表达式, "自定义失败提示文案(可选)"
- 布尔表达式:满足条件 = True → 用例放行;不满足 = False → 断言失败
- 自定义提示:失败时优先展示自定义信息,便于快速定位业务问题,自动化项目必加
基础示例:
python
# test_assert_base.py
def test_assert_demo():
expect = 200
actual = 200
# 成功,无报错
assert actual == expect
# 失败,抛出异常+自定义提示
actual2 = 500
assert actual2 == expect, f"接口状态码异常:预期{expect},实际{actual2}"
执行:pytest -vs test_assert_base.py
三、自动化高频场景:全类型断言实战(接口测试最常用)
1. 数值断言(状态码、数字结果)
==、!=、>、>=、<、<=,多用于接口响应码、返回数值校验
python
def test_num_assert():
code = 200
# 等于
assert code == 200, "请求成功状态码必须200"
# 大于
assert code > 100
# 不等于
assert code != 500
2. 字符串断言(返回文本、错误信息)
in / not in、==,校验返回内容是否包含指定关键字
python
def test_str_assert():
res_text = "login success"
assert "success" in res_text, "登录返回结果不含success"
assert "fail" not in res_text
3. 列表 / 元组断言(批量返回数据)
长度、成员存在性校验
python
def test_list_assert():
data_list = [10,20,30]
# 判断长度
assert len(data_list) ==3, "返回数据条数错误"
# 判断元素存在
assert 20 in data_list
4. 字典断言(接口返回 JSON,接口自动化重中之重)
键存在、键值匹配,90% 接口用例都会用到
python
def test_dict_assert():
resp = {"code":200,"msg":"ok","data":{"uid":1001}}
# 校验key是否存在
assert "code" in resp
# 校验value
assert resp["code"] ==200
# 嵌套字典取值断言
assert resp["data"]["uid"] ==1001
5. 布尔值断言
python
def test_bool_assert():
flag = True
assert flag is True
四、pytest.raises 异常断言:预判代码抛出指定异常
部分用例需要校验错误入参是否抛出预期异常,不用 try-except 捕获
使用**with pytest.raises(异常类型)**实现,异常匹配则用例通过,未抛异常则失败。
基础用法
python
import pytest
def test_exception():
# 预期传入非数字字符串,触发ValueError
with pytest.raises(ValueError):
int("abc123")
进阶:捕获异常信息
python
def test_exception_msg():
with pytest.raises(ValueError) as err_info:
int("test")
# 断言异常描述包含指定内容
assert "invalid literal for int()" in str(err_info.value)
五、自定义报错信息规范(项目实战最佳实践)
不要只写assert xxx ==xx,"断言失败"模糊提示,规范格式: assert 条件, f"【业务场景】预期XX,实际XX"
python
# 规范写法
resp_code = 404
expect_code =200
assert resp_code == expect_code, f"【用户登录接口】状态码异常:预期{expect_code},实际{resp_code}"
好处:流水线报错一眼定位接口与问题,节省排查时间。
六、Pytest 自动优化:复杂数据断言差异化报错
原生 Pytest 对长字符串、字典、列表会自动对比差异:
- 字符串不一致:高亮不同字符位置
- 字典不一致:标出 key 和 value 差异
- 列表不一致:提示第一个不匹配下标 示例报错:
python
E assert {'code': 200, 'msg': 'ok'} == {'code': 500, 'msg': 'fail'}
E Differing items:
E {'code': 200 != 500, 'msg': 'ok' != 'fail'}
七、开发踩坑注意事项
- 不要在 assert 表达式中写业务逻辑 :Python 使用
python -O运行时会全局禁用所有 assert,表达式内代码不会执行,只做结果判断。
python
# 错误:删除数据写在断言里,-O执行时代码失效
assert del_data() == True
# 正确:逻辑前置,只断言结果
res = del_data()
assert res == True
- 自定义提示要用 f-string 动态拼接实际值,固定文案无排查意义。
八、前后置 + 断言综合实战(整合上篇知识点)
类前置统一初始化请求、方法前置单用例准备数据,最后用断言校验结果,企业标准用例模板
python
class TestLoginApi:
def setup_class(self):
print("【类前置】初始化请求头、全局url")
self.headers = {"Content-Type":"application/json"}
def setup_method(self):
print("【方法前置】准备账号数据")
self.account = {"user":"test01","pwd":"123456"}
def test_login_success(self):
# 模拟接口返回
resp = {"code":200,"msg":"登录成功"}
# 多层断言
assert resp["code"] ==200, f"登录失败,状态码{resp['code']}"
assert "成功" in resp["msg"]