软件测试技能入门:从零构建自动化测试框架的实践指南

5次阅读
没有评论

共计 2325 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

测试基础概念扫盲

刚开始接触测试时,最常听到的就是单元测试和集成测试这两个术语。简单来说:

软件测试技能入门:从零构建自动化测试框架的实践指南

  • 单元测试:就像检查汽车的每个零件(发动机、轮胎等)是否合格,对应代码中的函数或方法测试
  • 集成测试:相当于把零件组装成整车后测试驾驶功能,验证多个模块组合后的运行效果

为什么需要自动化测试

手工测试时遇到过这些问题吗?

  1. 每次代码改动后,都要重复点击相同的测试流程
  2. 凌晨两点还在加班执行回归测试
  3. 总有些边界条件忘记测试,上线后突然崩掉

去年我们项目组引入自动化测试后,迭代速度从 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

避坑指南

  1. 断言失败无详细信息
  2. 错误写法:assert a == b
  3. 正确写法:assert a == b, f"期望{b},实际得到{a}"

  4. fixture 执行顺序混乱

  5. 使用 @pytest.fixture(scope="module") 控制生命周期
  6. 通过 autouse=True 自动执行

  7. 测试依赖外部服务

  8. 使用 pytest-mock 替换真实 API 调用
  9. 示例:
    def test_api(mocker):
        mocker.patch("requests.get", return_value={"code":200})
        # 测试代码...

学习资源推荐

  • 官方文档:PyTest 官方手册
  • 进阶书籍:《Python 测试驱动开发》
  • 实战项目:GitHub 搜索pytest-examples

刚开始可能觉得写测试代码浪费时间,但当项目迭代 3 个月后,你会感谢当初写了这些测试用例。我们团队现在每次提交代码,自动化测试能在 5 分钟内完成原来需要 2 天的手工验证。从今天开始,给你的代码加上安全防护网吧!

正文完
 0
评论(没有评论)