31-pytest-内置fixture之cache使用

本文详细介绍pytest内置fixture之cache的使用方法,包括如何利用cache参数快速定位及运行失败的测试用例,以及如何在测试过程中有效地读写缓存,并解决了中文缓存的写入和读取问题。


前言

  • pytest 运行完用例之后会生成一个 .pytest_cache 的缓存文件夹,用于记录用例的ids和上一次失败的用例。方便我们在运行用例的时候加上–lf 和 --ff 参数,快速运行上一次失败的用例。本篇来学习cache使用的使用

catch使用

参数说明
  • pytest -h 查看cache使用参数
  • –lf 也可以使用 --last-failed 仅运行上一次失败的用例
  • –ff 也可以使用 --failed-first 运行全部的用例,但是上一次失败的用例先运行
  • –nf 也可以使用 --new-first 根据文件插件的时间,新的测试用例会先运行
  • –cache-show=[CACHESHOW] 显示.pytest_cache文件内容,不会收集用例也不会测试用例,选项参数: glob (默认: ‘*’)
  • –cache-clear 测试之前先清空.pytest_cache文件
示例代码
# -*- coding: utf-8 -*-
# @Time    : 2022/3/26
# @Author  : 大海

import os


def test_01():
    a = "hello"
    b = "hello"
    assert a == b


def test_02():
    a = "hello"
    b = "hello world"
    assert a == b


def test_03():
    a = "hello"
    b = "hello world"
    assert a in b


def test_04():
    a = "hello"
    b = "hello world"
    assert a not in b


if __name__ == '__main__':
    os.system('pytest -s -v test_57.py --tb=line')
    
  • 运行后生成cache 文件
  • lastfailed 文件记录上一次运行失败的用例
    {
    “test_57.py::test_02”: true,
    “test_57.py::test_04”: true
    }
  • nodeids 文件记录所有用例的节点
    [
    “test_57.py::test_01”,
    “test_57.py::test_02”,
    “test_57.py::test_03”,
    “test_57.py::test_04”
    ]

在这里插入图片描述

cache-show
  • pytest --cache-show 查看cache
    在这里插入图片描述
cache-clear
  • –cache-clear 用于在测试用例开始之前清空cache的内容
# -*- coding: utf-8 -*-
# @Time    : 2022/3/26
# @Author  : 大海

import os


def test_01():
    a = "hello"
    b = "hello"
    assert a == b


def test_02():
    a = "hello"
    b = "hello world"
    assert a == b


def test_03():
    a = "hello"
    b = "hello world"
    assert a in b


def test_04():
    a = "hello"
    b = "hello world"
    assert a not in b


if __name__ == '__main__':
	# --cache-clear 运行用例前清空之前catche
    os.system('pytest -s -v test_57.py --tb=line --cache-clear')

写入/读取cache
  • 前置处理
# -*- coding: utf-8 -*-
# @Time    : 2022/3/26
# @Author  : 大海

import os
import pytest


@pytest.fixture()
def get_token(cache):
    """获取token"""
    token = "token12345678"
    # 写入cache
    cache.set("token", token)
    yield token


# 两种方式获取cache中的token值
def test_1(cache,get_token):
    # 方式1: 通过cache获取
    token= cache.get("token", None)
    print("获取到的token: {}".format(token))


def test_2(get_token):
    # 方式2:直接 通过get_token 获取返回值
    print("get_token fixture return: {}".format(get_token))


if __name__ == '__main__':
    os.system('pytest -s -v test_58.py')

在这里插入图片描述

  • 后置处理
# -*- coding: utf-8 -*-
# @Time    : 2022/3/26
# @Author  : 大海

import os
import pytest


@pytest.fixture()
def delete_token(cache):
    """后置处理"""
    yield
    # 获取cache
    token = cache.get("token", None)
    print("后置处理得到值: {}".format(token))
    # token 置空
    cache.set("token", None)


def test_1(cache, delete_token):
    # 执行用例后生成token
    token = "token12345678"
    # 写入cache
    cache.set("token", token)


if __name__ == '__main__':
    os.system('pytest -s -v test_59.py')

在这里插入图片描述

解决写入中文cache问题

*写入中文cache

# -*- coding: utf-8 -*-
# @Time    : 2022/3/26
# @Author  : 大海

import os
import pytest


@pytest.fixture()
def get_token(cache):
    """获取token"""
    token = "测试小白"
    cache.set("token", token)
    yield token


def test_1(cache, get_token):
    # 方式1: 通过cache获取
    token = cache.get("token", None)
    print("获取到的token: {}".format(token))


if __name__ == '__main__':
    os.system('pytest -s -v test_60.py')

在这里插入图片描述

  • 解决中文显示:在项目根目录conftest.py中,添加如下代码
from _pytest.cacheprovider import Cache
import json


def new_set(self, key: str, value: object) -> None:
   
    path = self._getvaluepath(key)
    try:
        if path.parent.is_dir():
            cache_dir_exists_already = True
        else:
            cache_dir_exists_already = self._cachedir.exists()
            path.parent.mkdir(exist_ok=True, parents=True)
    except OSError:
        self.warn("could not create cache path {path}", path=path, _ispytest=True)
        return
    if not cache_dir_exists_already:
        self._ensure_supporting_files()
    # ensure_ascii 置为False
    data = json.dumps(value, ensure_ascii=False, indent=2, sort_keys=True)
    try: 
        # 使用utf-8编码
        f = path.open("w", encoding='utf-8')
    except OSError:
        self.warn("cache could not write path {path}", path=path, _ispytest=True)
    else:
        with f:
            f.write(data)


Cache.set = new_set

在这里插入图片描述

解决读取中文cache问题
  • 中文正常写入后,读取会显示乱码,下面解决读取乱码的问题
    在这里插入图片描述
  • 解决控制台显示乱码: 在项目根目录conftest.py中,添加如下代码
def new_get(self, key, default):

    path = self._getvaluepath(key)
    try: 
    	# 设置 encoding='utf-8'
        with path.open("r", encoding='utf-8') as f:
            return json.load(f)
    except (ValueError, IOError, OSError):
        return default


Cache.get = new_get

在这里插入图片描述

<think> 我们正在讨论pytestfixture功能。根据之前的引用,fixturepytest的核心功能之一,用于准备测试环境(设置)和清理(拆卸)。它可以提高代码的复用性,减少重复代码,并且可以控制作用域(scope)以及自动清理资源。 我们将从以下几个方面详细介绍fixture: 1. fixture的基本概念和定义 2. fixture的作用域(scope) 3. fixture的依赖注入 4. 使用yield实现setup和teardown 5. 使用autouse参数自动执行fixture 6. fixture的参数化 7. 使用conftest.py共享fixture 8. 常用内置fixture(如tmpdir, capsys等) 9. 实际应用场景示例 注意:在回答中适当引用上述提供的参考内容,并在末尾添加引用标识。 开始详细回答: </think> ### Pytest Fixture 功能详解 FixturePytest 的核心功能,用于创建**可复用的测试资源**(数据库连接、临时文件、模拟对象等),支持依赖注入、作用域控制和自动清理。以下是详细解析: --- #### 一、Fixture 核心特性 | 特性 | 说明 | 示例 | |------|------|------| | **依赖注入** | 测试函数声明参数自动获取 Fixture | `def test_login(user):` | | **作用域控制** | 控制 Fixture 生命周期<br>`function`(默认), `class`, `module`, `session` | `@pytest.fixture(scope="module")` | | **自动清理** | 通过 `yield` 或 `addfinalizer` 释放资源 | `yield db_conn; db_conn.close()` | | **复用性** | 多个测试共享同一 Fixture | 多测试函数共用 `admin_token` | --- #### 二、基础用法 ##### 1. 定义与调用 Fixture ```python import pytest # 定义 Fixture @pytest.fixture def database(): conn = connect_db() # 资源初始化 yield conn # 返回资源 conn.close() # 自动清理 # 测试函数调用 def test_query(database): # 自动注入 data = database.query("SELECT * FROM users") assert len(data) > 0 ``` ##### 2. 作用域控制示例 ```python @pytest.fixture(scope="module") def admin_token(): # 整个测试模块只获取 1 次 Token token = login(username="admin", password="123456") yield token logout(token) # 模块结束自动清理 ``` --- #### 三、高级用法 ##### 1. 自动执行 Fixture (`autouse=True`) ```python @pytest.fixture(autouse=True) # 所有测试自动执行 def clear_cache(): cache.clear() # 每个测试前清理缓存 ``` ##### 2. Fixture 参数化 ```python @pytest.fixture(params=["Chrome", "Firefox"]) def browser(request): # request 内置对象 driver = webdriver.Browser(request.param) yield driver driver.quit() # 自动生成两个测试:test_search[Chrome] 和 test_search[Firefox] def test_search(browser): browser.get("https://example.com") ``` ##### 3. Fixture 依赖嵌套 ```python @pytest.fixture def user(admin_token): # Fixture 依赖其他 Fixture return create_user(token=admin_token) ``` --- #### 四、实际应用场景 ##### 1. Web 测试(Selenium) ```python @pytest.fixture(scope="class") def browser(): driver = webdriver.Chrome() yield driver driver.quit() # 类结束后关闭浏览器 class TestLogin: def test_login_page(self, browser): browser.get(LOGIN_URL) assert "Login" in browser.title ``` ##### 2. API 测试(令牌管理) ```python @pytest.fixture def auth_token(): token = requests.post(LOGIN_URL, json=credentials).json()["token"] yield token revoke_token(token) # 测试后回收令牌 ``` ##### 3. 数据库测试 ```python @pytest.fixture def db_session(): session = Session() yield session session.rollback() # 自动回滚未提交操作 session.close() ``` --- #### 五、最佳实践 1. **资源复用**:高频资源(如数据库连接)使用 `scope="session"` 2. **轻量级清理**:优先用 `yield` 替代 `addfinalizer` 3. **共享 Fixture**:将公共 Fixture 放入 `conftest.py`[^1] 4. **命名规范**:Fixtures 使用名词(如 `database`),测试函数使用 `test_` 前缀 > 通过 Fixture 将测试代码逻辑与资源管理分离,提升代码可读性和维护性[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习de测试小白

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值