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

以下是对 ​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  # 指定测试目录
<think>好的,我现在需要详细回答用户关于pytest中assert语句的用法和示例的问题。首先,我得回忆pytest的断言机制,和标准的Python assert有什么不同。记得pytest会重写assert语句,提供更详细的错误信息,这点很重要。 用户可能已经知道基本的assert用法,比如assert 1 == 2,但需要更深入的例子。我应该涵盖不同类型的断言,比如等式、不等式、包含、异常等。还要注意是否需要解释pytest如何自动捕获断言错误,并展示失败的具体信息。 然后,根据用户提供的引用,特别是引用[4],里面提到关键代码是“assert 表达式, 错误提示信息”,这说明用户可能需要关于自定义错误消息的例子。例如,当断言失败时,如何添加更清晰的提示,这需要给出示例,比如assert a == b, "数值不相等"。 接下来,我得组织内容结构。可能需要分点说明,比如基本用法、扩展断言、自定义错误信息、与第三方库的结合使用,比如NumPy的数组比较。这样结构更清晰,用户容易理解。 另外,用户提供的引用中有关于fixture和其他pytest用法的内容,虽然问题主要关注assert,但可能需要确保回答专注于断言部分,但如果有相关结合使用的例子,比如在fixture中使用断言,可能也需要提及,不过可能不太常见。 还需要检查是否有常见的陷阱或注意事项,比如在断言中使用生成器表达式可能导致的问题,或者某些对象比较需要特定方法,比如浮点数近似比较。比如,pytest.approx的使用,应该作为示例,因为这在测试数值时很常见。 然后,考虑用户可能的进阶需求,比如如何处理异常断言,使用pytest.raises上下文管理器。这也是assert语句的部分,需要详细说明和示例。 最后,生成相关问题,确保问题覆盖用户可能感兴趣的周边知识点,比如fixture的使用、测试顺序、参数化测试等,但要根据引用中的内容来生成,比如引用[2]、[3]、[5]提到的fixture和执行顺序,所以相关问题可以涉及这些方面。 现在,需要确保所有示例代码正确,符合LaTeX格式要求,行内公式用$...$,独立公式用$$...$$。但在这个问题中,可能数学公式不多,主要是代码块,所以要注意代码块的格式是否正确,用三个反引号包裹,并标明语言。 检查是否有遗漏的重要用法,比如集合的断言,字典的键值是否存在,或者使用正则表达式匹配字符串。这些也是常见的测试场景,应该包括进去。 总结,回答的结构应该是: 1. 基本用法:展示简单的等式、不等式断言。 2. 扩展断言类型:包含、类型检查、异常。 3. 自定义错误信息:如何在断言后添加消息。 4. 高级用法:比如浮点数近似比较,使用第三方库的数据结构。 5. 注意事项:比如避免在断言中执行有副作用的操作。 每个部分都需要代码示例,并确保正确性。同时,引用相关的引用内容,比如引用[4]中的例子,需要正确标注引用标识。 最后,生成的相关问题要基于用户提供的引用,比如关于fixture的使用、测试顺序、断言失败的处理等,这样能引导用户继续深入学习相关内容。</think>### pytest断言(assert)使用详解 pytest的断言机制通过重写Python原生`assert`语句实现自动化测试验证,具有智能错误提示功能。以下是具体用法分类说明: #### 、基础断言语法 ```python def test_math_operations(): # 等式验证 assert 5 + 3 == 8 # 正常通过 assert 2**3 == 7, "幂运算验证失败" # 触发AssertionError[^4] # 包含关系验证 assert 'hello' in 'hello world' assert 4 not in [1, 2, 3] ``` #### 二、扩展断言类型 ```python import pytest def test_data_structures(): # 集合比对 assert {'a': 1, 'b': 2} == {'b': 2, 'a': 1} # 字典无序性验证 # 类型检查 assert isinstance(3.14, float) # 异常捕获(必须使用pytest上下文管理器) with pytest.raises(ZeroDivisionError): _ = 1 / 0 ``` #### 三、高级验证方法 ```python def test_floating_point(): # 浮点数近似比较 assert 0.1 + 0.2 == pytest.approx(0.3, rel=1e-5) def test_numpy_data(): # 数组比对(Numpy专用) import numpy as np arr1 = np.array([1.0, 2.0]) arr2 = np.array([1.0, 2.001]) assert np.allclose(arr1, arr2, atol=0.01) ``` #### 四、自定义错误信息 ```python def test_user_message(): actual = 100 expected = 95 # 带调试信息的断言 assert actual == expected, f"预期值误差超过5%,实际值:{actual},预期值:{expected}" ``` #### 五、断言优化建议 1. 避免在断言中执行修改操作(如`assert list.pop()`) 2. 复杂对象建议使用专门比对方法(如`assertDictEqual`) 3. 大数据集验证优先检查关键特征值 $$ \text{断言执行效率公式:} T = k \times n + C \quad (n\text{为数据规模}) $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值