Python 单元测试进阶:pytest 参数化与 fixture

1. 参数化测试

参数化允许用不同数据运行同一测试逻辑,避免重复代码。使用 @pytest.mark.parametrize 装饰器实现:

import pytest

# 测试函数:平方计算
def square(x):
    return x ** 2

# 参数化测试用例
@pytest.mark.parametrize("input_val, expected", [
    (2, 4),    # 输入2,预期4
    (-3, 9),   # 输入-3,预期9
    (0, 0)     # 输入0,预期0
])
def test_square(input_val, expected):
    assert square(input_val) == expected

  • 优势:覆盖多组数据只需一个测试函数。
  • 语法@pytest.mark.parametrize("参数名", 数据列表),数据列表为元组列表。
2. Fixture 机制

Fixture 提供可复用的测试资源(如数据库连接、配置文件),通过 @pytest.fixture 定义:

import pytest

# 定义fixture:模拟数据库连接
@pytest.fixture
def db_connection():
    conn = create_dummy_db()  # 创建模拟数据库
    yield conn                # 返回资源
    conn.close()              # 测试后自动清理

# 使用fixture的测试
def test_db_query(db_connection):
    result = db_connection.execute("SELECT * FROM users")
    assert len(result) > 0

  • 特点
    • 自动清理yield 后的代码在测试结束后执行。
    • 作用域控制:通过 scope 参数(如 scope="module")管理生命周期。
  • 依赖注入:测试函数声明参数(如 db_connection)即可使用 fixture。
3. 参数化与 Fixture 结合

在 fixture 中生成动态数据,实现更灵活的测试:

import pytest

# Fixture生成动态数据
@pytest.fixture(params=["admin", "user", "guest"])
def user_role(request):
    return request.param  # 返回参数化数据

# 测试不同用户权限
def test_access_control(user_role):
    if user_role == "admin":
        assert has_admin_access() is True
    else:
        assert has_admin_access() is False

  • 流程
    1. Fixture 的 params 定义多组数据。
    2. request.param 获取当前测试的数据值。
    3. 测试函数通过参数接收数据。
4. 最佳实践
  • 参数化
    • 边界值测试:如 (999, 1000) 测试临界点。
    • 错误数据测试:如 ("abc", TypeError)
  • Fixture
    • 共享资源:用 scope="session" 避免重复初始化。
    • 模块化:将 fixture 放在 conftest.py 中供多文件使用。

示例场景:测试登录功能

  • 参数化:不同用户名/密码组合
  • Fixture:模拟登录会话
@pytest.mark.parametrize("username, password", [("user1", "pass1"), ("user2", "pass2")])
def test_login(login_session, username, password):
    response = login_session.post(username, password)
    assert response.status_code == 200

通过参数化和 fixture,可显著提升测试代码的简洁性和覆盖范围,同时确保资源高效管理。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐