【Python学习笔记】Flaky插件自动运行失败的测试

【注意】flaky和pytest-rerunfailures好像不能同时安装。否则flaky不好使。

测试过程中,你是否遇到过这样的情况:

1、大部分时间里测试都是通过的,只是偶尔会失败

2、测试偶尔失败的原因是,你的测试中使用了不是很稳定的第三方模块,你没有办法去提高第三方模块的稳定性

3、测试失败之后,往往重新执行测试,测试就能通过。

如果你使用的是nose或者py.test编写和执行测试,对于上面的情况,你可以删除最不稳定的case,或者使用@skip装饰器跳过经常测试失败的case。但是这并不是一个很好的方法。因为大量的case中,你没办法判断哪些case最容易失败。

那么有没有更好的办法,在这些不稳定的case失败之后,能够自动重新运行这些失败的case呢?当然有。那就是Flaky插件。

1、Flaky插件简介

安装官网的介绍,Flaky is a plugin for nose or py.test that automatically reruns flaky tests。他是一个nose和py.test的插件,能够在那些不稳定的case失败之后,重复执行这些case。官网:http://opensource.box.com/flaky/

 

2、Flaky安装

 

 
pip install flaky 

 

3、激活Flaky

在你测试过程中激活Flaky功能:

1)对于nose,执行

 

nosetests --with-flaky

2)对于py.test

 

 

py.test会自动激活Flaky不需要你做任何工作。

 

4、测试脚本中如何使用Flaky

4.1 将所有不稳定的case标记为flaky

 

from flaky import flaky

@flaky
def test_something_that_usually_passes(self):
    value_to_double = 21
    result = get_result_from_flaky_doubler(value_to_double)
    self.assertEqual(result, value_to_double * 2, 'Result doubled incorrectly.')

【解析】

 

只需在测试case上加上@flaky即可。这样,当这个测试失败的时候,会自动再次执行这测试1次。

flaky接收两个参数:max_runs and min_passes。max_runs表示测试失败之后,会重复执行这个测试的次数。min_passes表示执行max_runs这么多次中,成功的次数超过min_passes的话,则认为这个case就pass了。

我们将上面的脚本改为:

 

@flaky(max_runs=3, min_passes=2)
def test_something_that_usually_passes(self):
    """This test must pass twice, and it can be run up to three times."""
    value_to_double = 21
    result = get_result_from_flaky_doubler(value_to_double)
    self.assertEqual(result, value_to_double * 2, 'Result doubled incorrectly.')

【解析】

 

上面的脚本中有:@flaky(max_runs=3, min_passes=2),代表的意思是:如果test_something_that_usually_passes第一次执行失败了,将会再次重复执行它3次,如果这3次中有2次成功了,则认为这个测试通过了。

 

 

4.2 将测试类标记为flaky

@flaky
class TestMultipliers(TestCase):
    def test_flaky_doubler(self):
        value_to_double = 21
        result = get_result_from_flaky_doubler(value_to_double)
        self.assertEqual(result, value_to_double * 2, 'Result doubled incorrectly.')

    @flaky(max_runs=3)
    def test_flaky_tripler(self):
        value_to_triple = 14
        result = get_result_from_flaky_tripler(value_to_triple)
        self.assertEqual(result, value_to_triple * 3, 'Result tripled incorrectly.')

【解析】

在测试类上应用flaky,那么该测试类下面的所有测试,都将应用flaky。就拿上面的例子来讲,test_flaky_doubler失败后将重复执行1次,而test_flaky_tripler失败后将重复执行3次。

 

 

 

5、命令行中如何使用Flaky

5.1 不输出flaky测试报告

 

正常情况下,测试完成后将输出flaky的测试报告,该报告中显示了有哪些测试重复执行了以及重复执行的情况。

如果不想在测试完成后输出flaky报告,可以在执行测试的时候加上--no-flaky-report参数:

 

py.test --no-flaky-report

 

 

 

5.2 强制所有测试使用flaky

 

py.test --force-flaky

【说明】使用这个方法,就不需要在脚本中为每一个测试样例或者测试类指定@flaky。也不需要导入flaky模块。

 

5.3 命令行上设置重复执行次数

 

 

py.test --force-flaky --max-runs=3 --min-passes=2

这种情况下,在脚本中的max-runs和min-passes将覆盖命令行上的参数。也就是说最终起作用的参数还是脚本中的参数,如果脚本中没有指定这些参数,那么命令行上的参数才起作用。

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用pytest及其件编写测试用例的示例: 1. pytest-cov件: ```python import pytest def test_add(): assert add(2, 3) == 5 assert add(2, -3) == -1 def test_subtract(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError def test_coverage(): assert 0.8 < pytest_coverage() ``` 2. pytest-html件: ```python import pytest @pytest.mark.parametrize("x, y, expected", [(1, 2, 3), (2, 3, 5), (3, 4, 7)]) def test_add(x, y, expected): assert add(x, y) == expected def test_subtract(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError def test_html_report(tmpdir): html_path = tmpdir.join("report.html") pytest.main(["--html", str(html_path)]) ``` 3. pytest-xdist件: ```python import pytest @pytest.mark.parametrize("x, y, expected", [(1, 2, 3), (2, 3, 5), (3, 4, 7)]) def test_add(x, y, expected): assert add(x, y) == expected def test_subtract(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError @pytest.mark.parametrize("x, y, expected", [(1, 2, 3), (2, 3, 5), (3, 4, 7)]) def test_add_parallel(x, y, expected): assert add(x, y) == expected def test_subtract_parallel(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply_parallel(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide_parallel(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError ``` 4. pytest-bdd件: ```python import pytest from pytest_bdd import scenarios, given, when, then scenarios("calculator.feature") @given("the first number is <x>") def first_number(x): return int(x) @given("the second number is <y>") def second_number(y): return int(y) @when("the two numbers are added") def add_numbers(first_number, second_number): result = add(first_number, second_number) return result @when("the two numbers are subtracted") def subtract_numbers(first_number, second_number): result = subtract(first_number, second_number) return result @when("the two numbers are multiplied") def multiply_numbers(first_number, second_number): result = multiply(first_number, second_number) return result @when("the two numbers are divided") def divide_numbers(first_number, second_number): result = divide(first_number, second_number) return result @then("the result should be <result>") def check_result(add_numbers, subtract_numbers, multiply_numbers, divide_numbers, result): assert add_numbers == int(result) assert subtract_numbers == int(result) assert multiply_numbers == int(result) assert divide_numbers == int(result) ``` 5. pytest-mock件: ```python import pytest from unittest import mock @mock.patch("requests.get") def test_request_success(mock_get): mock_get.return_value.status_code = 200 result = request_api("http://www.example.com") assert result == "Success" @mock.patch("requests.get") def test_request_failure(mock_get): mock_get.return_value.status_code = 500 result = request_api("http://www.example.com") assert result == "Failure" ``` 6. pytest-flake8件: ```python import pytest def test_add(): assert add(2, 3) == 5 assert add(2, -3) == -1 def test_subtract(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError ``` 7. pytest-rerunfailures件: ```python import pytest @pytest.mark.flaky(reruns=5, reruns_delay=2) def test_add(): assert add(2, 3) == 5 assert add(2, -3) == -1 def test_subtract(): assert subtract(5, 3) == 2 assert subtract(5, -3) == 8 def test_multiply(): assert multiply(2, 3) == 6 assert multiply(2, -3) == -6 def test_divide(): assert divide(6, 3) == 2 assert divide(6, -3) == -2 assert divide(6, 0) == ZeroDivisionError ``` 以上是使用pytest及其件编写测试用例的示例,其中的add、subtract、multiply、divide和request_api是需要被测试的函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值