pytest 测试项目指南

下面是一个完整的 pytest 测试项目结构示例,包含了最佳实践和常见配置:

项目结构

Plain Text

复制代码
project-name/
├── src/                     # 应用程序源代码
│   └── app.py
├── tests/                   # 测试目录
│   ├── unit/                # 单元测试
│   │   ├── test_app.py
│   │   └── test_utils.py
│   ├── integration/         # 集成测试
│   │   └── test_api.py
│   ├── conftest.py          # 共享的fixture和配置
│   └── pytest.ini           # pytest配置文件
├── .gitignore
├── requirements.txt         # 项目依赖
└── setup.py                 # 安装脚本(可选)

关键文件内容

1. src/app.py (示例应用代码)

python

复制代码
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

2. tests/unit/test_app.py (单元测试)

python

复制代码
import pytest
from src.app import add, subtract, multiply, divide

class TestMathOperations:
    def test_add(self):
        assert add(2, 3) == 5
        assert add(-1, 1) == 0
        
    def test_subtract(self):
        assert subtract(5, 3) == 2
        assert subtract(3, 5) == -2
        
    def test_multiply(self):
        assert multiply(3, 4) == 12
        assert multiply(0, 5) == 0
        
    def test_divide(self):
        assert divide(10, 2) == 5
        
    def test_divide_by_zero(self):
        with pytest.raises(ValueError) as exc_info:
            divide(10, 0)
        assert "Cannot divide by zero" in str(exc_info.value)

3. tests/conftest.py (共享fixture)

python

复制代码
import pytest

# 共享fixture示例
@pytest.fixture
def sample_data():
    return {"a": 10, "b": 5}

# 配置pytest钩子
def pytest_addoption(parser):
    parser.addoption("--slow", action="store_true", default=False, 
                     help="Run slow tests")

def pytest_collection_modifyitems(config, items):
    if not config.getoption("--slow"):
        skip_slow = pytest.mark.skip(reason="need --slow option to run")
        for item in items:
            if "slow" in item.keywords:
                item.add_marker(skip_slow)

4. tests/pytest.ini (配置文件)

ini

复制代码
[pytest]
addopts = -v --cov=src --cov-report=html
testpaths = tests/unit tests/integration
markers =
    slow: marks tests as slow (deselect with '-m "not slow"')

5. requirements.txt (依赖文件)

Plain Text

复制代码
pytest==7.1.2
pytest-cov==3.0.0
requests==2.27.1  # 用于API测试

运行测试

基本命令

bash

复制代码
# 运行所有测试
pytest

# 运行特定目录下的测试
pytest tests/unit

# 运行特定文件中的测试
pytest tests/unit/test_app.py

# 运行特定类中的测试
pytest tests/unit/test_app.py::TestMathOperations

# 运行特定测试方法
pytest tests/unit/test_app.py::TestMathOperations::test_add

高级选项

bash

复制代码
# 生成覆盖率报告
pytest --cov=src

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

# 跳过标记为slow的测试
pytest -m "not slow"

# 在失败时启动调试器
pytest --pdb

# 并行运行测试(需要pytest-xdist)
pytest -n auto

最佳实践

  1. 命名约定

    • 测试文件:test_*.py*_test.py

    • 测试类:Test*

    • 测试方法:test_*

  2. 测试组织

    • 按功能模块分组测试

    • 将单元测试与集成测试分离

    • 使用标记(markers)分类测试

  3. 使用fixture

    • 避免重复设置代码

    • 创建可重用的测试环境

    • 使用conftest.py共享fixture

  4. 参数化测试

    python

    复制代码
    @pytest.mark.parametrize("a,b,expected", [
        (1, 2, 3),
        (-1, 1, 0),
        (10, 20, 30)
    ])
    def test_add(a, b, expected):
        assert add(a, b) == expected
  5. 测试覆盖率

    • 使用pytest-cov生成覆盖率报告

    • 目标覆盖关键业务逻辑

    • 但不要追求100%覆盖率(可能产生低价值测试)

  6. 持续集成

    • 在CI/CD流程中运行测试

    • 设置测试失败时的警报

    • 使用测试结果作为质量门禁

常见插件

  1. pytest-cov:代码覆盖率报告

  2. pytest-xdist:并行运行测试

  3. pytest-mock:简化mock使用

  4. pytest-django:Django项目支持

  5. pytest-asyncio:异步测试支持

  6. pytest-html:生成HTML报告

调试技巧

  1. 使用pytest --trace在测试开始时启动调试器

  2. 添加print()语句输出调试信息

  3. 使用pytest -s禁用输出捕获(显示print输出)

  4. 在失败测试中使用pdb

    python

    复制代码
    def test_failing():
        result = some_function()
        import pdb; pdb.set_trace()  # 在此设置断点
        assert result == expected

这个结构提供了一个健壮的测试基础,可以根据项目需求进行调整和扩展。

相关推荐
WiChP1 天前
【V0.1B6】从零开始的2D游戏引擎开发之路
java·log4j·游戏引擎
__zRainy__2 天前
Node.js 日志选型指南:Winston vs Log4js 全方位对比与实战
node.js·log4j·winston
希望永不加班7 天前
SpringBoot 集成测试:@SpringBootTest 与 MockMvc
java·spring boot·后端·log4j·集成测试
Howrun77711 天前
C++ 项目测试全指南:从 0 基础到落地实操
开发语言·c++·log4j
admin and root13 天前
从资产收集FUZZ接口到SQL注入案例
网络·数据库·sql·安全·web安全·渗透测试·log4j
Joy T13 天前
【Web3】智能合约质量保障工程:从单元测试到 Gas 效能优化
单元测试·log4j·web3·智能合约·hardhat
sg_knight15 天前
使用 Claude Code 写单元测试的实战方法
单元测试·log4j·ai编程
sthnyph16 天前
SpringBoot Test详解
spring boot·后端·log4j
brucelee18616 天前
Spring Boot 测试最佳实践
spring boot·后端·log4j
X-TIE16 天前
一次日志引发的“血案”:从 Log4j 1.x 锁竞争到 Log4j 2.x 异步写入实战
log4j