详细介绍:python pytest 学习笔记 Day02

深入理解与使用 Pytest 缓存机制

概述:缓存是什么?失败运行管理的原理

Pytest 的缓存机制由 cacheprovider 内置插件提供,主要用途有二:

  1. 记录测试会话状态:自动记录上一次运行的成功/失败用例等信息,用于支持 --lf(只运行失败用例)、--ff(先运行失败用例)等命令行功能。
  2. 跨用例共享数据:通过 cache fixture,允许测试用例有意识地设置和获取缓存值,实现测试间的数据传递(如共享登录 Token)。

缓存目录(默认 .pytest_cache)和文件由 pytest 在首次运行时自动创建和管理。

缓存的应用场景与核心操作

1. 利用会话状态缓存提高效率

这是缓存最常用的功能,旨在快速验证问题。

  • 重新运行上次失败的测试pytest --last-failed (或 --lf
  • 先运行失败用例,再运行其他pytest --failed-first (或 --ff
  • 显示当前缓存内容(不运行测试):pytest --cache-show
  • 清空缓存pytest --cache-clear
  • ​预览测试集合pytest --collect-only

2. 使用 cache Fixture 共享数据

当测试用例间存在依赖时,可以使用 cache fixture 来显式地读写数据。

python
import pytest
def test_login(cache):
    token = "sample_token_123"
    # 将 token 存入缓存,key 建议用 '项目名/模块名/变量名' 格式
    cache.set("my_project/auth/token", token)
    assert True
def test_access_protected_resource(cache):
    # 从缓存中获取 token,如果不存在则返回 None
    token = cache.get("my_project/auth/token", None)
    assert token is not None
    # ... 使用 token 进行后续测试

注意cache.set() 和 cache.get() 的值需要是 JSON 可序列化的类型。

最佳实践与工作流

智能化测试工作流

结合缓存与标记,可以建立高效的工作流。

  1. 快速迭代:只运行上次失败的用例

    pytest --lf -v

  2. 运行核心功能(标记为 'smoke' 的测试)

    pytest -m "smoke" -v

  3. 提交前运行完整套件,但遇到少量失败即停止(避免长时间等待)

    pytest --maxfail=5 -v

测试集合预览:--collect-only参数

核心功能

--collect-only

是 pytest 的诊断和预览参数,它让 pytest 只收集和显示测试用例,而不实际执行任何测试代码。

主要用途​预览测试集合​:查看哪些测试用例会被 pytest 发现和执行

​验证测试筛选​:确认 -k、-m等参数是否正确工作

​调试测试发现​:排查为什么某些测试用例没有被发现

​获取测试统计​:快速了解测试套件的规模和结构

基本用法

基本收集:显示所有测试用例

pytest --collect-only

结合详细模式:显示更详细信息

pytest --collect-only -v

结合缓存功能预览失败测试

pytest --lf --collect-only -v

验证筛选条件

pytest --collect-only -k "login" -vpytest --collect-only -m "smoke" -v

在 CI/CD 中的策略

在持续集成环境中,通常每次会是一个全新的环境,因此缓存可能不持久。但你可以:

  • 使用 pytest --cache-clear 作为流水线第一步,确保测试环境纯净。
  • 主要依赖 cache fixture 来在同一次测试会话的用例间传递数据,而非跨流水线构建。

Pytest 跳过测试用例指南

在 pytest 中跳过测试用例是非常实用的功能,允许您根据特定条件不执行某些测试。以下是几种主要的跳过方法:

1. 无条件跳过测试

使用 @pytest.mark.skip 装饰器可以无条件跳过测试:

import pytest
@pytest.mark.skip(reason="此功能尚未实现")
def test_feature_not_implemented():
    assert False  # 这个测试不会运行
@pytest.mark.skip("跳过原因:等待外部依赖")
def test_with_external_dependency():
    # 这个测试也不会运行
    pass

2. 有条件跳过测试

使用 @pytest.mark.skipif 装饰器可以根据条件跳过测试:

import pytest
import sys
### 根据Python版本跳过
@pytest.mark.skipif(sys.version_info < (3, 8), reason="需要 Python 3.8 或更高版本")
def test_python38_feature():
    assert True
### 根据操作系统跳过
@pytest.mark.skipif(sys.platform != "win32", reason="仅支持 Windows 平台")
def test_windows_only():
    assert True
### 自定义条件跳过
IS_CI = os.environ.get('CI') == 'true'
@pytest.mark.skipif(IS_CI, reason="不在CI环境中运行此测试")
def test_local_only():
    assert True

3. 运行时动态跳过

在测试函数内部使用 pytest.skip() 函数:

def test_dynamic_skip():
    # 检查某些条件
    if not some_condition:
        pytest.skip("条件不满足,跳过测试")
    # 正常的测试逻辑
    assert something == expected_value

4. 跳过整个测试模块

在模块顶部使用 pytestmark

import pytest
### 跳过整个模块
pytestmark = pytest.mark.skip("整个模块被跳过")
### 或者有条件跳过整个模块
pytestmark = pytest.mark.skipif(condition, reason="条件跳过整个模块")

5. 跳过类中的所有测试

@pytest.mark.skip(reason="跳过整个测试类")
class TestSkipEntireClass:
    def test_method1(self):
        assert False  # 不会运行
    def test_method2(self):
        assert False  # 不会运行

6. 预期失败测试(XFail)

虽然不是真正的跳过,但 xfail 用于标记预期会失败的测试:

@pytest.mark.xfail(reason="已知问题,正在修复")
def test_known_bug():
    assert False  # 预期会失败,但还会运行
@pytest.mark.xfail(condition, reason="条件性预期失败")
def test_conditionally_expected_to_fail():
    # 某些操作
    pass

7. 跳过与参数化结合

import pytest
@pytest.mark.parametrize("input_value", [
    pytest.param(1, id="case_1"),
    pytest.param(2, id="case_2"),
    pytest.param(3, marks=pytest.mark.skip(reason="跳过大于2的值")),
    pytest.param(4, marks=pytest.mark.skip(reason="跳过大于2的值"))
])
def test_with_skip_and_parametrize(input_value):
    assert input_value <= 2

查看跳过的测试

运行测试时,可以使用 -v 参数查看跳过的测试:

pytest -v

输出会显示: SKIPPED [1] test_file.py:3: 此功能尚未实现

使用 -rs 参数可以查看跳过的详细原因:

pytest -rs

✅ 关键收获

1. 缓存是基础:理解缓存机制是高效使用 pytest 的前提

2. 预览保安全:运行前先用 --collect-only 验证测试范围

3. 跳过得精准:合理跳过测试可以大幅提升执行效率

4. 组合出效果:这些功能组合使用才能发挥最大价值

posted @ 2025-11-20 16:49  gccbuaa  阅读(0)  评论(0)    收藏  举报