一、什么是 Pytest?

pytest 是 Python 中一个功能强大且广泛使用的测试框架。相比 Python 自带的 unittest,它语法简洁、功能丰富,支持参数化测试、插件扩展、断言简化等特性,极大提升了编写和运行测试的效率

二、安装 Pytest

在命令行中使用 pip 安装

pip install pytest

验证是否安装成功:

pytest --version

三、第一个测试用例

1. 创建测试文件

创建一个名为 test_sample.py 的文件:

# test_sample.pydef add(a, b):return a + bdef test_add():assert add(2, 3) == 5assert add(-1, 1) == 0assert add(0, 0) == 0

2. 运行测试

在终端中执行:

pytest test_sample.py

或简写:

(pytest 会自动发现当前目录下以 test_ 开头或 _test.py 结尾的文件)

输出示例:

============================= test session starts ==============================
collected 1 itemtest_sample.py .                                                         [100%]============================== 1 passed in 0.01s ===============================

✅ 表示测试通过。

四、Pytest 基本规则

  • 测试文件名以 test_ 开头 或 以 _test.py 结尾。
  • 测试函数名必须以 test_ 开头。
  • 使用 assert 关键字进行断言,无需导入 unittest.TestCase。

五、常见用法示例

1. 测试异常

使用 pytest.raises 捕获预期异常:

import pytestdef divide(a, b):if b == 0:raise ValueError("Cannot divide by zero")return a / bdef test_divide_by_zero():with pytest.raises(ValueError, match="Cannot divide by zero"):divide(10, 0)

2. 参数化测试(@pytest.mark.parametrize)

避免重复写多个测试用例。

import pytest@pytest.mark.parametrize("a, b, expected", [(2, 3, 5),(-1, 1, 0),(0, 0, 0),(100, -50, 50)
])
def test_add_parametrized(a, b, expected):assert add(a, b) == expected

运行后,每个参数组合都会作为独立测试运行。

3. 跳过测试

@pytest.mark.skip(reason="临时跳过这个测试")
def test_skip_example():assert False

4. 条件跳过

import sys@pytest.mark.skipif(sys.version_info < (3, 8), reason="需要 Python 3.8+")
def test_only_in_new_python():assert True

5. 标记测试(Mark)

可以给测试打标签,方便分组运行。

@pytest.mark.slow
def test_slow_function():import timetime.sleep(2)assert True@pytest.mark.smoke
def test_smoke():assert True

运行特定标记的测试:

pytest -m "smoke"        # 只运行 smoke 标记的测试
pytest -m "not slow"     # 排除 slow 测试

六、测试夹具(Fixtures)——核心功能

fixture 是 pytest 最强大的功能之一,用于准备测试环境(如数据库连接、临时文件等)。

示例:使用 fixture 提供测试数据

import pytest@pytest.fixture
def sample_data():return [1, 2, 3, 4, 5]def test_sum(sample_data):assert sum(sample_data) == 15def test_length(sample_data):assert len(sample_data) == 5

fixture 作用域(scope)

@pytest.fixture(scope="module")
def db_connection():print("连接数据库")conn = "database_connection"yield connprint("关闭数据库")
  • scope="function":每个测试函数前运行(默认)
  • scope="module":每个测试文件前运行一次
  • scope="session":整个测试会话只运行一次

七、测试组织结构建议

推荐目录结构:

my_project/
│
├── src/
│   └── myapp.py
│
├── tests/
│   ├── test_myapp.py
│   └── test_utils.py
│
└── pytest.ini  (可选配置文件)

八、常用命令行选项

命令

说明

pytest

运行所有测试

pytest test_file.py::test_function

运行指定函数

pytest -v

显示详细结果

pytest -x

遇到失败立即停止

pytest --tb=short

简化 traceback 输出

pytest --collect-only

仅收集测试,不运行

pytest -k "add or divide"

运行包含 "add" 或 "divide" 的测试

pytest --html=report.html

生成 HTML 报告(需安装pytest-html)

九、安装常用插件

# 生成 HTML 报告
pip install pytest-html
pytest --html=report.html# 重新运行失败的测试
pip install pytest-rerunfailures
pytest --reruns 3# 输出覆盖率报告
pip install pytest-cov
pytest --cov=src tests/

十、最佳实践建议

✅ 测试函数保持单一职责

✅ 使用 parametrize 减少重复代码

✅ 合理使用 fixture 管理测试依赖

✅ 给测试加清晰的命名,如 test_add_positive_numbers

✅ 避免测试之间相互依赖

✅ 使用 .gitignore 忽略测试报告和缓存文件(如 __pycache__, .pytest_cache)

十一、完整示例项目

src/calculator.py:

def multiply(x, y):return x * y

tests/test_calculator.py:

import pytest
from src.calculator import multiply@pytest.mark.parametrize("x,y,result", [(2, 3, 6),(0, 100, 0),(-1, 5, -5),(1, 1, 1)
])
def test_multiply(x, y, result):assert multiply(x, y) == result

运行:

pytest tests/test_calculator.py -v

十二、参考资料

  • 官方文档:https://docs.pytest.org/
  • GitHub: https://github.com/pytest-dev/pytest
  • 插件仓库:https://plugincompat.herokuapp.com/

🎉 恭喜!你已经掌握了 Pytest 的基本用法。现在可以开始为你的项目编写清晰、高效的自动化测试了!