pytest官方文档 6.2 中文翻译版(第十四章):Cache:管理跨测试的状态

本文档介绍了pytest的Cache管理功能,包括如何重新执行失败的测试用例、查看和清除缓存,以及Stepwise逐步调试。提供命令行参数如`--lf`、`--ff`和`--cache-clear`,并展示了插件如何利用`config.cache`对象。对于故障排查和CI流程非常有用。
摘要由CSDN通过智能技术生成

14.1 用法

这个插件提供了两个命令行参数用于在测试失败的时候重新运行失败的用例:

  • –lf, --last-failed 只重新运行失败的用例
  • –ff, --failed-first 先重新运行失败的用例,然后运行其他的

为了执行清理(通常情况下不需要),使用 --cache-clear 允许我们在测试运行之前删除所有的之前运行的cache。
其他的插件可以在pytest执行的时候访问 config.cache 对象来获取一个json格式的值。
注意:这个插件默认是开启的,如果你需要也可以关上:查看18.3,使用名字 声明/卸载 插件(这个插件的内部名字是 cacheprovider)。
译者注:这个插件对于排错很有用,例如CI上面报了错,你可以直接使用 pytest -lf 来执行刚刚出错的一些用例

14.2 重新执行失败用例或先执行失败用例

首先,我们创建50个测试,其中两个会失败:

# content of test_50.py
import pytest


@pytest.mark.parametrize("i", range(50))
def test_num(i):
	if i in (17, 25):	
		pytest.fail("bad luck")

第一次运行你会看到两个失败:

$ pytest -q
.................F.......F........................ [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
2 failed, 48 passed in 0.12s

如果你之后再用 pytest --lf 运行:

$ pytest --lf
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 2 items
run-last-failure: rerun previous 2 failures
test_50.py FF [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
============================ 2 failed in 0.12s =============================

在上一次运行中,你只运行了两个之前失败的测试,其余48个测试没有被运行。
现在,如果你使用 --ff 选项,所有的测试都会被运行,但是之前失败的用例会被先运行(从一连串的FF和点中可以看出):

$ pytest --ff
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 50 items
run-last-failure: rerun previous 2 failures first
test_50.py FF................................................ [100%]
================================= FAILURES =================================
_______________________________ test_num[17] _______________________________
i = 17
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
_______________________________ test_num[25] _______________________________
i = 25
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
> pytest.fail("bad luck")
E Failed: bad luck
test_50.py:7: Failed
========================= short test summary info ==========================
FAILED test_50.py::test_num[17] - Failed: bad luck
FAILED test_50.py::test_num[25] - Failed: bad luck
======================= 2 failed, 48 passed in 0.12s =======================

新的 --nf,–new-first选项:最新的测试先运行,老的在之后运行,在这种情况下,执行顺序是根据最后修改时间的,最近修改的最先运行。

14.3 上次没有测试失败时候的行为

如果上一次没有失败,或者是没有找到cached,pytest可以被配置为运行全部测试或者不运行任何一个测试,使用 --last-failed-no-failures,它可以被配置为下面的几个值:

pytest --last-failed --last-failed-no-failures all # 运行所有测试
pytest --last-failed --last-failed-no-failures none # 不运行任何测试

14.4 新的 config.cache 对象

在插件或者conftest.py中支持使用pytest配置对象获取缓存的值。下面是一个简单的插件的例子,它实现了一个可以在多次pytest调用之前重复使用之前创建的状态的夹具:

# content of test_caching.py
import pytest
import time

def expensive_computation():
	print("running expensive computation...")

@pytest.fixture
def mydata(request):
	val = request.config.cache.get("example/value", None)
	if val is None:
		expensive_computation()
		val = 42
	request.config.cache.set("example/value", val)
return val

def test_function(mydata):
	assert mydata == 23

第一次运行,你会看到下面的结果:

$ pytest -q
F [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________
mydata = 42
def test_function(mydata):
> assert mydata == 23
E assert 42 == 23
test_caching.py:20: AssertionError
-------------------------- Captured stdout setup ---------------------------
running expensive computation...
========================= short test summary info ==========================
FAILED test_caching.py::test_function - assert 42 == 23
1 failed in 0.12s

再运行一次,测试会从cache中读取值,信息就不会被打印出来了:

$ pytest -q
F [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________
mydata = 42
def test_function(mydata):
> assert mydata == 23
E assert 42 == 23
test_caching.py:20: AssertionError
========================= short test summary info ==========================
FAILED test_caching

在 22.3.2中可以看到更多的信息。

14.5 查看cache信息

你可以使用 --cache-show 参数查看cache的信息:

$ pytest --cache-show
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
cachedir: $PYTHON_PREFIX/.pytest_cache
--------------------------- cache values for '*' ---------------------------
cache/lastfailed contains:
{'test_50.py::test_num[17]': True,
'test_50.py::test_num[25]': True,
'test_assert1.py::test_function': True,
'test_assert2.py::test_set_comparison': True,
'test_caching.py::test_function': True,
'test_foocompare.py::test_compare': True}
cache/nodeids contains:
['test_50.py::test_num[0]',
'test_50.py::test_num[10]',
'test_50.py::test_num[11]',
'test_50.py::test_num[12]',
'test_50.py::test_num[13]',
'test_50.py::test_num[14]',
'test_50.py::test_num[15]',
'test_50.py::test_num[16]',
'test_50.py::test_num[17]',
'test_50.py::test_num[18]',
'test_50.py::test_num[19]',
'test_50.py::test_num[1]',
'test_50.py::test_num[20]',
'test_50.py::test_num[21]',
'test_50.py::test_num[22]',
'test_50.py::test_num[23]',
'test_50.py::test_num[24]',
'test_50.py::test_num[25]',
'test_50.py::test_num[26]',
'test_50.py::test_num[27]',
'test_50.py::test_num[28]',
'test_50.py::test_num[29]',
'test_50.py::test_num[2]',
'test_50.py::test_num[30]',
'test_50.py::test_num[31]',
'test_50.py::test_num[32]',
'test_50.py::test_num[33]',
'test_50.py::test_num[34]',
'test_50.py::test_num[35]',
'test_50.py::test_num[36]',
'test_50.py::test_num[37]',
'test_50.py::test_num[38]',
'test_50.py::test_num[39]',
'test_50.py::test_num[3]',
'test_50.py::test_num[40]',
'test_50.py::test_num[41]',
'test_50.py::test_num[42]',
'test_50.py::test_num[43]',
'test_50.py::test_num[44]',
'test_50.py::test_num[45]',
'test_50.py::test_num[46]',
'test_50.py::test_num[47]',
'test_50.py::test_num[48]',
'test_50.py::test_num[49]',
'test_50.py::test_num[4]',
'test_50.py::test_num[5]',
'test_50.py::test_num[6]',
'test_50.py::test_num[7]',
'test_50.py::test_num[8]',
'test_50.py::test_num[9]',
'test_assert1.py::test_function',
'test_assert2.py::test_set_comparison',
'test_caching.py::test_function',
'test_foocompare.py::test_compare']
cache/stepwise contains:
[]
example/value contains:
42
========================== no tests ran in 0.12s ===========================

–cache-show 可以使用一个模式通配符来对于结果进行一个过滤:

$ pytest --cache-show example/*
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
cachedir: $PYTHON_PREFIX/.pytest_cache
----------------------- cache values for 'example/*' -----------------------
example/value contains:
42
========================== no tests ran in 0.12s===========================

14.6 清空cache

你可以通过添加–cache-clear选项来指示pytest清除所有缓存文件和值:

pytest --cache-clear

这在一些对于独立性要求比运行速度更重要的类似于CI这样的系统中是十分有用的。

14.7 Stepwise

另一个与–lf类似的是 -x,特别适合你已经知道一个很大的测试集一定会失败。–sw,–stepwise 允许你一次修复一个测试。测试执行过程中只要碰到失败就会停下来。在下一次调用的时候,测试会从上一次失败的用例开始,直到遇到下一个失败。你可以使用 --stepwise-skip 来忽略一次测试的失败,在第二个失败的时候才停下来。当你被一个失败的测试卡住想之后修复它的时候,这个能力十分有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值