Pytest学习(十三)- 重复执行之pytest-repeat的使用

本文详细介绍了pytest-repeat插件的使用方法,包括安装步骤、基本命令行参数、不同执行模式及示例代码。该插件能帮助自动化测试脚本进行多次执行或失败重试,便于发现偶发性bug。

写在前面

这个插件,可以帮助我们很好的解决自动化测试过程中的一些偶线性bug难以复现的问题,但前提是,当前自动化脚本是独立的,不依赖任何其他脚本。个人觉得还是失败重运行的一种体现,就和TestNG是一样的,下面我们来一起感受下这个插件的使用吧。

环境准备

  • py.test版本 ≥ 2.8
  • Python 2.7、3.4+

安装插件

pip3 install pytest-repeat -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

如何使用

结合《生成HTML报告插件之pytest-html的使用》这篇文章,还是结合输出的html报告来看比较直观。

1、举个例子

# -*- coding: utf-8 -*-
# @Time    : 2020/11/29 8:52
# @Author  : longrong.lang
# @FileName: test_repeat.py
# @Software: PyCharm
# @Cnblogs :https://www.cnblogs.com/longronglang

def test_repeat():
    import random
    num = random.randint(1, 9)
    print(f"\n输出随机数:{num}")
    assert num == 2

2、结合失败重跑,并输出报告

使用示例如下:

# 使用下面哪条命令都可执行
pytest --html=report.html --self-contained-html  -s --reruns=5 --count=3 test_repeat.py
pytest --html=report.html --self-contained-html  -s --reruns=5 --count 3 test_repeat.py

执行效果如下:

生成html报告如下:

注意:

  • reruns=5:意思是失败重运行5次
  • count=3:意思是重复执行3次

3、仅重复执行

使用示例如下:

# 使用下面哪条命令都可执行
pytest --html=report.html --self-contained-html  -s --count=3 test_repeat.py
pytest --html=report.html --self-contained-html  -s --count 3 test_repeat.py

执行效果如下:

很明显这里显示的只是重复执行3次

4、重复测试直到失败

这在我们实际测试中,就很受用了,验证偶现问题,可以反复运行相同的测试脚本直到失败,可以将pytest的 -x 选项与pytest-repeat结合使用,以强制测试运行程序在第一次失败时停止。
使用示例如下:

py.test --count=1000 -x test_repeat.py

执行效果如下:

5、使用注解的形式来实现重复执行

使用 @pytest.mark.repeat(count)标记在测试方法即可,这和TestNg的 @Test(invocationCount = 5)是一样的。
示例代码如下:

@pytest.mark.repeat(3)
def test_repeat2():
    print("\n 测试脚本")

执行效果如下:

repeat-scope的使用

命令行参数作用:可以覆盖默认的测试用例执行顺序,类似fixture的scope参数

  • function:默认,范围针对每个用例重复执行,再执行下一个用例
  • class:以class为用例集合单位,重复执行class里面的用例,再执行下一个
  • module:以模块为单位,重复执行模块里面的用例,再执行下一个
  • session:重复整个测试会话,即所有测试用例的执行一次,然后再执行第二次

1、重复执行class里面的用例

即class中的测试方法,不存在混合情况,示例代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2020/11/29 10:07
# @Author  : longrong.lang
# @FileName: test_repeatClass.py
# @Software: PyCharm
# @Cnblogs :https://www.cnblogs.com/longronglang
class TestRepeatClass1(object):
    def test_repeat1(self):
        print("\n repeat 1。。。。。。。。。")

class TestRepeatClass2(object):
    def test_repeat2(self):
        print("\n repeat 2。。。。。。。。。")

命令行执行:

pytest -s --count=2 --repeat-scope=class test_repeatClass.py

执行效果如下:

2、以模块为单位,重复执行模块里面的用例

可以理解为混合,既有类也有单独的测试方法,示例代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2020/11/29 10:07
# @Author  : longrong.lang
# @FileName: test_repeatClass.py
# @Software: PyCharm
# @Cnblogs :https://www.cnblogs.com/longronglang

def test_repeat1():
    print("test_repeat1")


class TestRepeatClass1(object):
    def test_repeat1(self):
        print("\n repeat 1。。。。。。。。。")

执行命令:

pytest -s --count=2 --repeat-scope=moudle test_repeatClass.py

执行效果如下: 兼容性问题
pytest-repeat不能与unittest.TestCase测试类一起使用。无论--count设置多少,这些测试始终仅运行一次,并显示警告

系列参考文章:https://www.cnblogs.com/poloyy/category/1690628.html

<think>我们正在讨论如何使用pytest-repeat插件来循环运行多条测试用例。根据引用[1],我们了解到pytest-repeat可以结合`-x`选项在第一次失败时停止。但用户现在想了解的是如何循环运行局部多条用例(即只重复运行部分测试用例)。 在pytest中,我们可以使用标记(mark)来指定要重复运行的测试用例。pytest-repeat提供了`@pytest.mark.repeat(n)`装饰器,可以标记在单个测试函数上,使其重复运行n次。 但是,如果用户想要同时重复运行多个测试用例(即一个测试类中的多个测试方法,或者多个测试函数),我们可以通过以下方式实现: 1. 对每个需要重复的测试用例单独标记`@pytest.mark.repeat(n)`。 2. 使用pytest的`pytestmark`特性在类级别应用重复,这样类中的所有测试方法都会重复。 3. 通过命令行对选定的测试用例应用重复使用`-k`选择测试用例,然后结合`--count`参数),但这种方式只能对整个选中的集合应用相同的重复次数。 然而,用户要求的是“局部多条用例”,也就是指定一部分用例重复,另一部分不重复。我们可以采用标记的方法,只给需要重复的用例打上标记。 具体步骤: 假设我们有以下测试文件(test_example.py),其中包含三个测试用例:test_one, test_two, test_three。我们只想重复test_one和test_two。 方法一:使用装饰器标记每个需要重复的测试函数。 ```python import pytest class TestExample: @pytest.mark.repeat(5) def test_one(self): assert 1 == 1 @pytest.mark.repeat(5) def test_two(self): assert 2 == 2 def test_three(self): assert 3 == 3 ``` 这样,test_one和test_two将分别运行5次,而test_three只运行1次。 方法二:如果多个测试函数需要重复相同的次数,我们可以使用类装饰器,但pytest-repeat并没有直接提供类装饰器。不过,我们可以通过给类设置一个pytestmark属性来批量标记: ```python import pytest @pytest.mark.repeat(5) class TestExample: def test_one(self): assert 1 == 1 def test_two(self): assert 2 == 2 def test_three(self): assert 3 == 3 ``` 但是注意,这样类中的所有测试方法(test_one, test_two, test_three)都会重复5次。如果只想重复其中一部分,这种方法就不合适了。 因此,如果只想重复类中的部分测试方法,还是应该使用方法一,即逐个标记。 方法三:通过命令行选择测试用例并设置重复次数。例如,我们只想重复运行名字包含"one"或"two"的测试用例,可以这样: ```bash pytest --count=5 -k "one or two" test_example.py ``` 但是,这种方法会使得匹配到的所有测试用例都重复5次,而其他测试用例只运行一次(且不会被重复)。需要注意的是,`-k`参数用于选择测试用例,这里使用了表达式来选择测试用例名称中包含"one"或"two"的用例。 总结:推荐使用方法一(标记装饰器)来精确控制需要重复的测试用例,或者使用方法三(命令行选择)来批量选择多个测试用例并重复。 另外,引用[1]中提到了`-x`选项,它可以在第一次失败时就停止。这个选项同样可以配合标记使用。 示例:重复运行标记为`repeat`的测试用例5次,并在第一次失败时停止: ```bash pytest --count=5 -x -m repeat test_example.py ``` 这里我们假设已经用`@pytest.mark.repeat`标记了测试用例,但注意`-m repeat`是选择标记名为`repeat`的测试用例,而`@pytest.mark.repeat`是一个特殊的标记,它实际上并不打上`repeat`标记。所以,如果我们想通过标记来选择,可以自定义一个标记,例如: ```python import pytest @pytest.mark.myrepeat @pytest.mark.repeat(5) def test_one(): ... ``` 然后命令行: ```bash pytest --count=5 -x -m myrepeat test_example.py ``` 但是,这里`--count=5`和`@pytest.mark.repeat(5)`会冲突,因为两者都指定了重复次数。实际上,我们只需要一种方式指定重复次数。 因此,更清晰的做法是:对于需要重复的测试用例,我们统一使用`@pytest.mark.repeat(n)`标记,然后命令行中不需要再使用`--count`,而是通过`-m`来选择标记(但这里我们并不需要,因为标记已经包含了重复次数)。如果我们想同时使用`-x`,可以: ```bash pytest -x test_example.py ``` 这样,标记了`@pytest.mark.repeat(5)`的测试用例会运行5次,但注意`-x`会在整个测试会话第一次失败时就停止,包括重复运行中的失败。也就是说,如果某个重复运行的测试用例在第一次运行时就失败了,那么整个测试就会停止,不会继续重复运行剩下的次数,也不会运行后面的测试用例。 如果用户希望即使重复运行的测试用例中某个失败,也要继续运行完剩下的重复次数,那么`-x`就不合适了。pytest-repeat本身没有提供在重复运行中忽略失败继续运行的选项,但我们可以结合pytest的其他插件或功能来实现。 因此,回答用户问题:使用pytest-repeat循环局部多条用例的方法主要有两种: 1. 在需要重复的测试函数上使用`@pytest.mark.repeat(n)`装饰器。 2. 在命令行中使用`--count`参数配合`-k`参数选择测试用例。 根据具体需求选择合适的方法。 注意:如果用户只想重复运行某几个测试用例,并且这些测试用例没有共同的命名模式,那么使用装饰器逐个标记是最直接的方法。 最后,我们生成相关问题: §§相关问题§§ 1. 如何只重复运行pytest中失败的测试用例? 2. 在重复运行测试用例时,如何忽略中间失败而继续运行直到完成所有重复次数? 3. pytest-repeat能否与pytest-xdist(并行运行)一起使用?如何配置? 4. 除了pytest-repeat,还有哪些pytest插件可以用于测试用例的重复执行? </think> ### 使用 `pytest-repeat` 循环运行局部多条用例的方法 在 `pytest` 中,通过 `pytest-repeat` 插件实现**局部多条用例的循环运行**主要有两种方式,核心思路是通过标记(Mark)或命令行参数精确控制需重复的测试范围: --- #### 方法 1:使用 `@pytest.mark.repeat` 装饰器(推荐) 为**需要重复的测试函数或类**单独添加装饰器,其他用例不受影响: ```python import pytest # 重复执行 3 次 @pytest.mark.repeat(3) def test_login(): assert login("user", "pass") is True # 重复执行 5 次 @pytest.mark.repeat(5) def test_payment(): assert process_payment(100) == "success" # 不重复的用例 def test_logout(): assert logout() is True ``` --- #### 方法 2:命令行动态选择用例 通过 `-k` 或 `-m` 筛选需重复的用例,结合 `--count` 指定次数: ```bash # 用例名包含 "check" 的重复运行 4 次 pytest --count=4 -k "check" test_api.py # 标记为 "smoke" 的用例重复运行 2 次 pytest --count=2 -m smoke test_ui.py ``` --- #### 结合失败控制(如 `-x` 选项) 在重复运行中首次失败时立即停止(引用[1]): ```bash # 重复运行 5 次,首次失败时停止 pytest --count=5 -x test_critical.py ``` --- ### 应用场景示例 假设需要**重复测试购物车结算流程**(多步骤组合),但跳过其他非核心功能: ```python import pytest @pytest.mark.repeat(10) # 重复 10 次 class TestCheckout: def test_add_item(self): assert add_to_cart("item1") == 1 def test_payment(self): assert checkout(cart_total=100) == "paid" # 不重复的普通用例 def test_search(): assert search("book") == 5 ``` 执行后: - `TestCheckout` 类中的两个用例各运行 **10 次** - `test_search` 仅运行 **1 次** --- ### 注意事项 1. **避免全局重复**: 不要直接使用 `pytest --count=N`(会重复所有用例),需配合 `-k`/`-m` 限定范围。 2. **与参数化结合**: 可与 `@pytest.mark.parametrize` 嵌套使用,实现“参数组合 × 重复次数”的测试矩阵。 3. **结果统计**: 重复运行的用例在报告中显示为独立条目(如 `test_payment[1/5]`)。 > **提示**:对复杂场景(如正交组合测试),建议结合 `pytest-pairwise` 等插件减少用例数量(引用[2])。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值