pytest官方Tutorial所有示例详解(一)
以下是对 pytest 官方 Tutorial 的详细解析,结合代码示例和关键概念说明,帮助你逐步掌握 pytest 的核心功能。
1. 安装与运行第一个测试
安装
pip install -U pytest
验证安装:
pytest --version
第一个测试文件
创建文件 test_sample.py
:
# test_sample.py
def func(x):return x + 1def test_func():assert func(3) == 4 # 断言:验证 func(3) 的结果是否为 4
运行测试
pytest test_sample.py
输出解析:
pytest
会自动发现以test_
开头的文件(如test_sample.py
)和函数(如test_func
)。- 若断言失败,会显示详细的错误信息(如实际值和期望值的差异)。
2. 断言(Assertions)
pytest 直接使用 Python 的 assert
语句,无需复杂的断言方法。例如:
def test_integers():a = 5b = 6assert a + 1 == b # 验证 a+1 是否等于 bdef test_strings():s = "hello"assert s.upper() == "HELLO" # 验证字符串大写转换
关键点:
- 断言失败时,pytest 会显示失败的具体表达式(如
assert 5 + 1 == 7
会明确提示6 != 7
)。
3. 测试类(Test Classes)
将相关测试组织到类中,类名需以 Test
开头,方法名以 test_
开头:
# test_class.py
class TestClass:def test_one(self):x = "this"assert "h" in x # 验证字符串包含字符 'h'def test_two(self):x = "hello"assert hasattr(x, "check") # 验证对象是否有 'check' 属性(预期失败)
运行方式:
pytest test_class.py -v # -v 显示详细输出
输出示例:
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
4. 跳过测试(Skipping Tests)
使用 @pytest.mark.skip
跳过特定测试:
# test_skip.py
import pytest@pytest.mark.skip(reason="暂时跳过此测试")
def test_skip_example():assert False # 此测试会被跳过,不会执行
运行结果:
test_skip.py::test_skip_example SKIPPED (暂时跳过此测试)
5. 参数化测试(Parametrization)
通过 @pytest.mark.parametrize
对同一测试函数传入多组参数:
# test_parametrize.py
import pytest@pytest.mark.parametrize("a, b, expected", [(1, 2, 3),(4, 5, 9),(10, 20, 30),
])
def test_add(a, b, expected):assert a + b == expected
运行结果:
test_parametrize.py::test_add[1-2-3] PASSED
test_parametrize.py::test_add[4-5-9] PASSED
test_parametrize.py::test_add[10-20-30] PASSED
优势:避免重复代码,覆盖多组输入场景。
6. Fixture(测试夹具)
Fixture 用于提供测试所需的资源(如数据库连接、临时文件等),通过 @pytest.fixture
定义:
# test_fixture.py
import pytest@pytest.fixture
def sample_data():return [1, 2, 3] # 提供测试数据def test_sum(sample_data):assert sum(sample_data) == 6 # 使用 fixture 提供的数据
运行方式:
pytest test_fixture.py -v
关键点:
- Fixture 可以跨多个测试函数复用。
- 支持作用域(如
scope="module"
表示整个模块共享一个 Fixture 实例)。
7. 临时目录与文件(tmp_path Fixture)
pytest 内置 tmp_path
Fixture,用于创建临时目录和文件:
# test_tmp_path.py
def test_create_file(tmp_path):d = tmp_path / "subdir" # 创建子目录d.mkdir()p = d / "hello.txt" # 创建文件p.write_text("Hello, pytest!")assert p.read_text() == "Hello, pytest!"assert len(list(tmp_path.iterdir())) == 1 # 验证目录内容
用途:测试文件操作时无需清理临时文件。
8. 捕获异常(Exception Testing)
使用 pytest.raises
验证代码是否抛出预期异常:
# test_exception.py
import pytestdef test_zero_division():with pytest.raises(ZeroDivisionError): # 验证是否抛出 ZeroDivisionError1 / 0
扩展:还可检查异常的具体信息:
with pytest.raises(ValueError) as excinfo:int("xyz")
assert "invalid literal" in str(excinfo.value)
9. 标记(Markers)
通过标记(如 @pytest.mark.slow
)分类测试,选择性运行:
# test_markers.py
import pytest@pytest.mark.slow
def test_slow_function():import timetime.sleep(2)assert True# 运行时指定标记
# pytest -m slow # 仅运行标记为 slow 的测试
# pytest -m "not slow" # 排除 slow 测试
10. 配置文件(pytest.ini)
通过配置文件 pytest.ini
自定义 pytest 行为(如设置默认命令行选项):
# pytest.ini
[pytest]
addopts = -v -ra # 默认启用详细输出 (-v) 和失败重试 (-ra)
testpaths = tests # 指定测试目录