pytest官方Tutorial所有示例详解(一)

发布于:2025-07-28 ⋅ 阅读:(13) ⋅ 点赞:(0)

以下是对 ​pytest 官方 Tutorial​ 的详细解析,结合代码示例和关键概念说明,帮助你逐步掌握 pytest 的核心功能。


1. 安装与运行第一个测试

安装

pip install -U pytest

验证安装:

pytest --version

第一个测试文件

创建文件 test_sample.py

# test_sample.py
def func(x):
    return x + 1

def 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 = 5
    b = 6
    assert a + 1 == b  # 验证 a+1 是否等于 b

def 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 pytest

def test_zero_division():
    with pytest.raises(ZeroDivisionError):  # 验证是否抛出 ZeroDivisionError
        1 / 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 time
    time.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  # 指定测试目录

网站公告

今日签到

点亮在社区的每一天
去签到