Pytest教程

Pytest官方教程-14-缓存:使用跨执行状态

2019-04-22  本文已影响45人  韩志超

目录:

  1. 安装及入门
  2. 使用和调用方法
  3. 原有TestSuite使用方法
  4. 断言的编写和报告
  5. Pytest fixtures:清晰 模块化 易扩展
  6. 使用Marks标记测试用例
  7. Monkeypatching/对模块和环境进行Mock
  8. 使用tmp目录和文件
  9. 捕获stdout及stderr输出
  10. 捕获警告信息
  11. 模块及测试文件中集成doctest测试
  12. skip及xfail: 处理不能成功的测试用例
  13. Fixture方法及测试用例的参数化
  14. 缓存: 使用跨执行状态
  15. unittest.TestCase支持
  16. 运行Nose用例
  17. 经典xUnit风格的setup/teardown
  18. 安装和使用插件
  19. 插件编写
  20. 编写钩子(hook)方法
  21. 运行日志
  22. API参考
    1. 方法(Functions)
    2. 标记(Marks)
    3. 钩子(Hooks)
    4. 装置(Fixtures)
    5. 对象(Objects)
    6. 特殊变量(Special Variables)
    7. 环境变量(Environment Variables)
    8. 配置选项(Configuration Options)
  23. 优质集成实践
  24. 片状测试
  25. Pytest导入机制及sys.path/PYTHONPATH
  26. 配置选项
  27. 示例及自定义技巧
  28. Bash自动补全设置

缓存:使用跨执行状态

版本2.8中的新功能。

用法

该插件提供了两个命令行选项,用于重新运行上次pytest调用的失败:

对于清理(通常不需要),--cache-clear选项允许在测试运行之前删除所有跨会话缓存内容。

其他插件可以访问config.cache对象以在调用之间设置/获取 json可编码pytest

注意

此插件默认启用,但如果需要可以禁用:请参阅 按名称取消激活/取消注册插件(此插件的内部名称为 cacheprovider)。

首先只重新运行故障或故障

首先,让我们创建50个测试调用,其中只有2个失败:

# 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:6: 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:6: Failed
2 failed, 48 passed in 0.12 seconds

如果你然后运行它--lf

$ pytest --lf
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 50 items / 48 deselected / 2 selected
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:6: 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:6: Failed
================= 2 failed, 48 deselected in 0.12 seconds ==================

你只运行了上次运行中的两个失败测试,​​而尚未运行48个测试(“取消选择”)。

现在,如果使用该--ff选项运行,将运行所有测试,但首先执行先前的失败(从一系列FF和点中可以看出):

$ pytest --ff
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.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:6: 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:6: Failed
=================== 2 failed, 48 passed in 0.12 seconds ====================

新的--nf--new-first选项:首先运行新的测试,然后是其余的测试,在这两种情况下,测试也按文件修改时间排序,最新的文件首先出现。

上次运行中没有测试失败时的行为

如果在上次运行中没有测试失败,或者没有lastfailed找到缓存数据,pytest则可以使用该--last-failed-no-failures选项配置运行所有测试或不运行测试,该选项采用以下值之一:

pytest --last-failed --last-failed-no-failures all    # run all tests (default behavior)
pytest --last-failed --last-failed-no-failures none   # run no tests and exit

新的config.cache对象

插件或conftest.py支持代码可以使用pytest config对象获取缓存值。这是一个实现pytest fixture的基本示例插件:显式,模块化,可伸缩,它在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

如果你是第一次运行此命令,则可以看到print语句:

$ pytest -q
F                                                                    [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________

mydata = 42

 def test_function(mydata):
>       assert mydata == 23
E       assert 42 == 23

test_caching.py:17: AssertionError
-------------------------- Captured stdout setup ---------------------------
running expensive computation...
1 failed in 0.12 seconds

如果再次运行它,将从缓存中检索该值,并且不会打印任何内容:

$ pytest -q
F                                                                    [100%]
================================= FAILURES =================================
______________________________ test_function _______________________________

mydata = 42

 def test_function(mydata):
>       assert mydata == 23
E       assert 42 == 23

test_caching.py:17: AssertionError
1 failed in 0.12 seconds

有关更多详细信息,请参阅config.cache

检查缓存内容

你始终可以使用--cache-show命令行选项查看缓存的内容 :

$ pytest --cache-show
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.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 -------------------------------
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_caching.py::test_function']
cache/stepwise contains:
  []
example/value contains:
  42

======================= no tests ran in 0.12 seconds =======================

清除缓存内容

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

pytest --cache-clear

对于Continuous Integration服务器的调用,建议使用此选项,其中隔离和正确性比速度更重要。

逐步修复失败用例

作为替代方案,尤其是对于你希望测试套件的大部分都会失败的情况,允许你一次修复一个。测试套件将运行直到第一次失败然后停止。在下次调用时,测试将从上次失败测试继续,然后运行直到下一次失败测试。你可以使用该选项忽略一个失败的测试,并在第二个失败的测试中停止测试执行。如果你遇到失败的测试而只是想稍后忽略它,这将非常有用。--lf -x``--sw``--stepwise``--stepwise-skip

上一篇下一篇

猜你喜欢

热点阅读