我来手把手教你创建一个简单的pytest测试案例。

第一步:安装pytest

# 在命令行中执行
pip install pytest

# 或者使用清华镜像加速
pip install pytest -i https://pypi.tuna.tsinghua.edu.cn/simple

第二步:创建项目结构

创建一个项目文件夹,比如 pytest_demo,结构如下:

pytest_demo/
├── calculator.py     # 被测试的代码
├── test_calculator.py # 测试文件
└── requirements.txt  # 依赖文件(可选)

第三步:编写被测试的代码

calculator.py - 一个简单的计算器类:

class Calculator:
    """一个简单的计算器类"""
    
    def add(self, a, b):
        """加法"""
        return a + b
    
    def subtract(self, a, b):
        """减法"""
        return a - b
    
    def multiply(self, a, b):
        """乘法"""
        return a * b
    
    def divide(self, a, b):
        """除法"""
        if b == 0:
            raise ValueError("除数不能为零")
        return a / b
    
    def is_even(self, number):
        """判断是否为偶数"""
        return number % 2 == 0

第四步:编写测试代码

test_calculator.py - pytest测试文件:

import pytest
from calculator import Calculator

# 创建测试夹具(fixture) - 在每个测试前初始化Calculator
@pytest.fixture
def calc():
    """返回一个Calculator实例"""
    return Calculator()

# 测试加法
def test_add(calc):
    """测试加法功能"""
    assert calc.add(2, 3) == 5
    assert calc.add(-1, 1) == 0
    assert calc.add(0, 0) == 0

# 测试减法
def test_subtract(calc):
    """测试减法功能"""
    assert calc.subtract(10, 5) == 5
    assert calc.subtract(5, 10) == -5

# 测试乘法
def test_multiply(calc):
    """测试乘法功能"""
    assert calc.multiply(3, 4) == 12
    assert calc.multiply(0, 5) == 0

# 测试除法
def test_divide(calc):
    """测试除法功能"""
    assert calc.divide(10, 2) == 5
    assert calc.divide(5, 2) == 2.5

# 测试除数为零的情况 - 应该抛出异常
def test_divide_by_zero(calc):
    """测试除数为零的异常情况"""
    with pytest.raises(ValueError) as exc_info:
        calc.divide(10, 0)
    assert "除数不能为零" in str(exc_info.value)

# 测试偶数判断
def test_is_even(calc):
    """测试偶数判断"""
    assert calc.is_even(2) is True
    assert calc.is_even(3) is False
    assert calc.is_even(0) is True

# 使用参数化测试 - 测试多组数据
@pytest.mark.parametrize("a,b,expected", [
    (1, 2, 3),
    (5, 5, 10),
    (-1, 1, 0),
    (0, 0, 0),
])
def test_add_parametrized(calc, a, b, expected):
    """参数化测试加法"""
    assert calc.add(a, b) == expected

# 使用mark标记测试
@pytest.mark.slow  # 自定义标记
def test_large_numbers(calc):
    """测试大数字"""
    assert calc.add(1000000, 2000000) == 3000000

第五步:运行测试

在项目根目录 pytest_demo 中打开命令行,运行以下命令:

1. 运行所有测试

pytest

2. 显示详细信息

pytest -v  # verbose模式,显示每个测试的详细信息

3. 运行特定测试文件

pytest test_calculator.py

4. 运行特定测试函数

pytest test_calculator.py::test_add  # 只运行test_add函数

5. 运行带标记的测试

pytest -m slow  # 只运行标记为slow的测试

6. 生成测试报告

pytest --tb=short  # 简短错误信息
pytest --tb=no     # 不显示错误详情
pytest -q          # 安静模式,只显示结果

第六步:查看测试输出

成功时你会看到类似这样的输出:

============================= test session starts =============================
platform win32 -- Python 3.9.0, pytest-7.0.0, pluggy-1.0.0
rootdir: C:\pytest_demo
collected 9 items

test_calculator.py .........                                           [100%]

============================== 9 passed in 0.12s ==============================

如果有测试失败,pytest会显示详细的错误信息。

第七步:创建pytest配置文件(可选)

在项目根目录创建 pytest.ini 文件:

[pytest]
# 测试文件匹配模式
python_files = test_*.py
# 测试函数匹配模式
python_functions = test_*
# 测试类匹配模式
python_classes = Test*

# 添加自定义标记
markers =
    slow: 标记为慢速测试
    fast: 标记为快速测试
    
# 默认命令行选项
addopts = -v --tb=short

完整流程总结

  1. 安装:pip install pytest
  2. 创建文件结构:源文件 + test_开头的测试文件
  3. 编写测试:使用 assert 进行断言
  4. 运行测试:在命令行执行 pytest
  5. 查看结果:根据输出调整代码

常见问题解决

  1. 找不到模块:确保在项目根目录运行pytest
  2. 测试没被发现:确保测试文件以 test_ 开头,测试函数以 test_ 开头
  3. 导入错误:使用相对导入或设置PYTHONPATH

进阶功能(等你熟悉后)

# 1. 测试夹具的setup和teardown
@pytest.fixture
def setup_teardown():
    print("测试开始前的准备")
    yield  # 这里返回给测试函数使用
    print("测试结束后的清理")

# 2. 使用类组织测试
class TestCalculator:
    def test_add(self, calc):
        assert calc.add(1, 2) == 3
    
    def test_multiply(self, calc):
        assert calc.multiply(2, 3) == 6

# 3. 跳过测试
@pytest.mark.skip(reason="功能未实现")
def test_future_feature():
    assert False

# 4. 条件跳过
@pytest.mark.skipif(sys.version_info < (3, 8), reason="需要Python 3.8以上")
def test_python38_feature():
    # ...

现在你已经有了一个完整的pytest项目!试着运行一下,看看所有测试是否通过。

更多推荐