Pytest----如何重执行失败用例

简介: Pytest----如何重执行失败用例

一、只重新执行失败用例

使用 --lf 参数,只执行上次失败的用例
test_demo.py代码如下:

import pytest

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

首先使用pytest执行一遍

$ pytest
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items                                                                                                                                                      

tests\test_demo.py .................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

tests\test_demo.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

tests\test_demo.py:7: Failed
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_num[17] - Failed: bad luck
FAILED tests/test_demo.py::test_num[25] - Failed: bad luck
===================================================================== 2 failed, 48 passed in 0.40s =====================================================================

然后使用--lf参数执行,结果如下,可以发现,此时只执行了两个测试用例

$ pytest --lf
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 2 items                                                                                                                                                       
run-last-failure: rerun previous 2 failures

tests\test_demo.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

tests\test_demo.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

tests\test_demo.py:6: Failed
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_num[17] - Failed: bad luck
FAILED tests/test_demo.py::test_num[25] - Failed: bad luck
========================================================================== 2 failed in 0.33s ===========================================================================

二、先执行失败用例然后再执行其他用例

使用 --lf 参数,只执行上次失败的用例
test_demo.py代码如下:

import pytest

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

首先使用pytest执行一遍

$ pytest
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items                                                                                                                                                      

tests\test_demo.py .................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

tests\test_demo.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

tests\test_demo.py:7: Failed
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_num[17] - Failed: bad luck
FAILED tests/test_demo.py::test_num[25] - Failed: bad luck
===================================================================== 2 failed, 48 passed in 0.40s =====================================================================

然后使用 --ff参数,先执行失败用例,再执行其他用例

$ pytest --ff
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items                                                                                                                                                      
run-last-failure: rerun previous 2 failures first

tests\test_demo.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

tests\test_demo.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

tests\test_demo.py:6: Failed
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_num[17] - Failed: bad luck
FAILED tests/test_demo.py::test_num[25] - Failed: bad luck
===================================================================== 2 failed, 48 passed in 0.40s =====================================================================

三、当上次无失败用例时--lf参数的效果

当上一次没有用例失败是,当再次使用 --lf时,默认动作是执行全部

test_demo.py代码如下:

import pytest

@pytest.mark.parametrize("i", range(50))
def test_num(i):
    assert 1==1

首先执行pytest结果如下:

$ pytest
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items                                                                                                                                                      

tests\test_demo.py ..................................................                                                                                             [100%]

========================================================================== 50 passed in 0.30s ==========================================================================

此时使用 --lf参数执行结果如下:

$ pytest --lf
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items                                                                                                                                                      
run-last-failure: no previously failed tests, not deselecting items.

tests\test_demo.py ..................................................                                                                                             [100%]

========================================================================== 50 passed in 0.30s ==========================================================================

当再机上 --last-failed-no-failures none 参数,则可以设置此时不在执行
执行结果如下:

$ pytest --lf --last-failed-no-failures none
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 50 items / 50 deselected                                                                                                                                      
run-last-failure: no previously failed tests, deselecting all items.

======================================================================== 50 deselected in 0.23s ========================================================================

四、前后两次执行之间可通过cache传递数据

通过request.config.cache.set 向缓存中写入数据,request.config.cache.get从缓存中获取数据

test_demo.py代码如下:

import pytest

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

第一次执行执行结果如下,这里因为测试过多次,所以加上 --cache-clear 清理缓存

$ pytest -s --cache-clear
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 1 item                                                                                                                                                        

test_demo.py example/value is None, now begin to set value to example/value
F

=============================================================================== FAILURES ===============================================================================
____________________________________________________________________________ test_function _____________________________________________________________________________

mydata = 42

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

test_demo.py:14: AssertionError
======================================================================= short test summary info ========================================================================
FAILED test_demo.py::test_function - assert 42 == 23
========================================================================== 1 failed in 0.10s ===========================================================================

再次执行如下,发现此时美哦与“example/value is None, now begin to set value to example/value”打印了,说明缓存中写入成功了

$ pytest -s
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 1 item                                                                                                                                                        

test_demo.py F

=============================================================================== FAILURES ===============================================================================
____________________________________________________________________________ test_function _____________________________________________________________________________

mydata = 42

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

test_demo.py:14: AssertionError
======================================================================= short test summary info ========================================================================
FAILED test_demo.py::test_function - assert 42 == 23
========================================================================== 1 failed in 0.09s ===========================================================================

此时可以通过 pytest --cache-show 查看缓存中的数据,可以发现,确实可以看到example\value的值为42

$ pytest --cache-show
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
cachedir: D:\src\blog\tests\.pytest_cache
------------------------------------------------------------------------- cache values for '*' -------------------------------------------------------------------------
cache\lastfailed contains:
  {'test_demo.py::test_function': True}
cache\nodeids contains:
  ['test_demo.py::test_function']
cache\stepwise contains:
  []
example\value contains:
  42

======================================================================== no tests ran in 0.01s =========================================================================

五、调试用例再次执行从上次失败处执行

可以通过 --sw 参数,即--stepwise,做到调试用例,当遇到失败时,就停下来,然后手工去修复用例,用例修复后,再执行时从上次失败处执行,遇到失败后再次停下来......

test_demo.py代码如下,即执行10个用例,其中,当i为1,3,5时,用例失败,下面一步一步演示如何调试

import pytest


@pytest.mark.parametrize("i", range(10))
def test_num(i):
    print(i)
    if i in [1,3,5]:
        pytest.fail("bad luck")

执行测试,如下,

$ pytest --sw
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 10 items                                                                                                                                                      
stepwise: no previously failed tests, not skipping.

test_demo.py .F

=============================================================================== FAILURES ===============================================================================
_____________________________________________________________________________ test_num[1] ______________________________________________________________________________

i = 1

    @pytest.mark.parametrize("i", range(10))
    def test_num(i):
        print(i)
        if i in [1,3,5]:
>           pytest.fail("bad luck")
E           Failed: bad luck

test_demo.py:8: Failed
------------------------------------------------------------------------- Captured stdout call -------------------------------------------------------------------------
1
======================================================================= short test summary info ========================================================================
FAILED test_demo.py::test_num[1] - Failed: bad luck
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: Test failed, continuing from this test next run. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
===================================================================== 1 failed, 1 passed in 0.14s ======================================================================

当i为0时,成功,当i为1时,失败,停止下来,因此失败一个,通过一个,此时将代码修复,如下:

import pytest


@pytest.mark.parametrize("i", range(10))
def test_num(i):
    print(i)
    if i in [3,5]:
        pytest.fail("bad luck")

再次执行如下

$ pytest --sw
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 10 items / 1 deselected / 9 selected                                                                                                                          
stepwise: skipping 1 already passed items.

test_demo.py ..F

=============================================================================== FAILURES ===============================================================================
_____________________________________________________________________________ test_num[3] ______________________________________________________________________________

i = 3

    @pytest.mark.parametrize("i", range(10))
    def test_num(i):
        print(i)
        if i in [3,5]:
>           pytest.fail("bad luck")
E           Failed: bad luck

test_demo.py:8: Failed
------------------------------------------------------------------------- Captured stdout call -------------------------------------------------------------------------
3
======================================================================= short test summary info ========================================================================
FAILED test_demo.py::test_num[3] - Failed: bad luck
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: Test failed, continuing from this test next run. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================== 1 failed, 2 passed, 1 deselected in 0.15s ===============================================================

此时,即i从1开始执行,当i为1,2时成功,当i为3时失败,因此通过2个,失败一个,再次修复测试脚本如下:

import pytest


@pytest.mark.parametrize("i", range(10))
def test_num(i):
    print(i)
    if i in [5]:
        pytest.fail("bad luck")

再次执行

$ pytest --sw
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 10 items / 3 deselected / 7 selected                                                                                                                          
stepwise: skipping 3 already passed items.

test_demo.py ..F

=============================================================================== FAILURES ===============================================================================
_____________________________________________________________________________ test_num[5] ______________________________________________________________________________

i = 5

    @pytest.mark.parametrize("i", range(10))
    def test_num(i):
        print(i)
        if i in [5]:
>           pytest.fail("bad luck")
E           Failed: bad luck

test_demo.py:8: Failed
------------------------------------------------------------------------- Captured stdout call -------------------------------------------------------------------------
5
======================================================================= short test summary info ========================================================================
FAILED test_demo.py::test_num[5] - Failed: bad luck
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: Test failed, continuing from this test next run. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================== 1 failed, 2 passed, 3 deselected in 0.15s ===============================================================

此时i从3开始执行,当i为3,4时成功,当i为5时失败,因此通过2个,失败一个,再次修复脚本如下:

import pytest


@pytest.mark.parametrize("i", range(10))
def test_num(i):
    print(i)
    if i in []:
        pytest.fail("bad luck")

再次执行

$ pytest --sw
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 10 items / 5 deselected / 5 selected                                                                                                                          
stepwise: skipping 5 already passed items.

test_demo.py .....                                                                                                                                                [100%]

=================================================================== 5 passed, 5 deselected in 0.03s ====================================================================

此时i从5开始执行,当i为5,6,7,8,9时成功,因此成功5个,执行完毕,从而完成脚本的调试

目录
相关文章
|
9月前
|
测试技术
包含用例执行时间的测试报告代码
包含用例执行时间的测试报告代码
|
9月前
|
测试技术
Cypress 运行失败用例的方法
Cypress 运行失败用例的方法
116 0
|
测试技术
30-pytest-重复执行用例-pytest-repeat
30-pytest-重复执行用例-pytest-repeat
30-pytest-重复执行用例-pytest-repeat
|
测试技术 Python
Pytest用例执行的先后顺序
Pytest用例执行的先后顺序
134 0
|
测试技术
29-pytest-运行上次失败用例
29-pytest-运行上次失败用例
|
测试技术
15-pytest-自定义用例执行顺序
15-pytest-自定义用例执行顺序
|
测试技术 Python
02-pytest-用例运行规则
02-pytest-用例运行规则
|
测试技术 C++
pytest pytest.ini配置 用例分组 用例跳过
pytest pytest.ini配置 用例分组 用例跳过
|
测试技术
pytest学习和使用14-Pytest用例执行结果有哪几种状态?
pytest学习和使用14-Pytest用例执行结果有哪几种状态?
98 0
|
测试技术 数据库
【pytest】case多执行慢?pytest-xdist分布式测试,了解一下
【pytest】case多执行慢?pytest-xdist分布式测试,了解一下
【pytest】case多执行慢?pytest-xdist分布式测试,了解一下