共计 2325 个字符,预计需要花费 6 分钟才能阅读完成。
测试基础概念扫盲
刚开始接触测试时,最常听到的就是单元测试和集成测试这两个术语。简单来说:

- 单元测试:就像检查汽车的每个零件(发动机、轮胎等)是否合格,对应代码中的函数或方法测试
- 集成测试:相当于把零件组装成整车后测试驾驶功能,验证多个模块组合后的运行效果
为什么需要自动化测试
手工测试时遇到过这些问题吗?
- 每次代码改动后,都要重复点击相同的测试流程
- 凌晨两点还在加班执行回归测试
- 总有些边界条件忘记测试,上线后突然崩掉
去年我们项目组引入自动化测试后,迭代速度从 2 周缩短到 3 天。下面分享具体实现方法。
框架选型:PyTest 为什么胜出
对比过主流框架后,我最终选择 PyTest,因为:
- RobotFramework 需要额外学习关键字语法
- Unittest 的断言写法不够人性化
- PyTest 的插件生态丰富(已有 800+ 插件)
安装只需一行命令:
pip install pytest pytest-html
实战:从零搭建测试框架
项目结构规范
推荐这样组织测试代码:
project/
├── src/ # 被测代码
├── tests/
│ ├── __init__.py
│ ├── conftest.py # 共享 fixture
│ ├── unit/ # 单元测试
│ └── feature/ # 功能测试
└── requirements.txt
第一个测试用例
测试用户登录功能(带中文注释):
# tests/feature/test_login.py
import pytest
# 被测方法(实际开发中放在 src 目录)def login(username, password):
"""模拟登录校验"""
if not username or not password:
return "用户名密码不能为空"
return "登录成功" if password == "123456" else "密码错误"
# 测试类名称建议用 Test 开头
class TestLogin:
# 正常场景测试
def test_success_login(self):
assert login("admin", "123456") == "登录成功"
# 异常场景测试
def test_wrong_password(self):
assert login("admin", "111111") == "密码错误"
运行测试:
pytest -v tests/feature/test_login.py
参数化测试实战
当需要测试多组数据时,可以用@pytest.mark.parametrize:
# 在 TestLogin 类中添加:@pytest.mark.parametrize("user,pwd,expected", [("","", "用户名密码不能为空"), # 空输入
("admin", None, "用户名密码不能为空"), # None 值测试
("guest", "123456", "登录成功") # 多用户场景
])
def test_login_params(self, user, pwd, expected):
assert login(user, pwd) == expected
神奇的 fixture
fixture 可以理解为测试的 ” 脚手架 ”,比如测试前准备数据库连接:
# conftest.py
import pytest
@pytest.fixture
def db_connection():
"""模拟数据库连接"""
print("\n 建立数据库连接")
conn = "MockDB"
yield conn # 测试执行阶段
print("\n 关闭数据库连接") # 清理操作
# 测试文件中直接使用:def test_query(db_connection):
assert "Mock" in db_connection
持续集成:GitHub Actions 配置
在项目根目录创建.github/workflows/test.yml:
name: Python Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install pytest
pip install -r requirements.txt
- name: Run tests
run: pytest --junitxml=report.xml
- name: Upload report
uses: actions/upload-artifact@v2
with:
name: test-report
path: report.xml
避坑指南
- 断言失败无详细信息
- 错误写法:
assert a == b -
正确写法:
assert a == b, f"期望{b},实际得到{a}" -
fixture 执行顺序混乱
- 使用
@pytest.fixture(scope="module")控制生命周期 -
通过
autouse=True自动执行 -
测试依赖外部服务
- 使用
pytest-mock替换真实 API 调用 - 示例:
def test_api(mocker): mocker.patch("requests.get", return_value={"code":200}) # 测试代码...
学习资源推荐
- 官方文档:PyTest 官方手册
- 进阶书籍:《Python 测试驱动开发》
- 实战项目:GitHub 搜索
pytest-examples
刚开始可能觉得写测试代码浪费时间,但当项目迭代 3 个月后,你会感谢当初写了这些测试用例。我们团队现在每次提交代码,自动化测试能在 5 分钟内完成原来需要 2 天的手工验证。从今天开始,给你的代码加上安全防护网吧!
正文完
