Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I retry for failed tests in Pytest

Tags:

python

pytest

Can I ask for failed tests in pytest Some number of restarts (retries). For example: if 2 attempts fail and the third succeeds, then the total result succeeds

like image 574
user10551458 Avatar asked Oct 24 '18 10:10

user10551458


People also ask

Can we rerun failed test cases in JUnit?

Rerun Failed Tests with JUnit 4 ExampleWe need two classes, one of them is our Rule Class's RetryRule and the other is our Test Class's RetryRuleTest. In RetryRuleTest class, I will open www.swtestacademy.com and get its title and check it with the WRONG expected title.

What does pytest fail do?

A subtle difference between ERROR and FAIL If you call pytest. fail inside a test, it's a FAIL status for that test (or XFAIL, if it has xfail mark). But, if you call it from a fixture, the test, which depends on this fixture, is getting ERROR state.

How do you run the same test multiple times in pytest?

Repeating a test Each test collected by pytest will be run count times. If you want to override default tests executions order, you can use --repeat-scope command line option with one of the next values: session , module , class or function (default). It behaves like a scope of the pytest fixture.

What is the maximum number of tests that pytest can run in parallel?

Can be a positive integer or auto which evenly divides tests among the workers up to 50 concurrent tests.


2 Answers

AFAIK, this is implemented in pytest-rerunfailures plugin. Take a look into.

e.g.

$ pip install pytest-rerunfailures
$ pytest --reruns 5
like image 82
Slam Avatar answered Oct 22 '22 00:10

Slam


Using the pytest-rerunfailures package is a good approach, but sometimes it may not be strong enough. If you need custom options, this implementation can be useful.

from pytest import fixture
from functools import wraps
import time


def retry_test(stop_max_attempt_number=5, wait_fixed=5):
    def decorator(test_func_ref):
        @wraps(test_func_ref)
        def wrapper(*args, **kwargs):
            retry_count = 1

            while retry_count < stop_max_attempt_number:
                try:
                    return test_func_ref(*args, **kwargs)

                except AssertionError as assert_error:
                    assert_message, _ = assert_error.__str__().split("\n")
                    print(f"Retry error: \"{test_func_ref.__name__}\" --> {assert_message}. "
                          f"[{retry_count}/{stop_max_attempt_number - 1}] Retrying new execution in {wait_fixed} second(s)")
                    time.sleep(wait_fixed)
                    retry_count += 1

            # Preserve original traceback in case assertion Failed        
            return test_func_ref(*args, **kwargs)

        return wrapper
    return decorator


class Test:
    @fixture(scope="class")
    def env(self):
        return {
            "retry": 10,
            "sleep": 5,
            "data": iter([{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 10}])

        }

    @retry_test(stop_max_attempt_number=5, wait_fixed=2)
    def test_product(self, env):
        message_product = next(env["data"], None)
        print(f"Reading message. {message_product}")

        if message_product["id"] == 10:
            assert True, "Message was intercepted"

        else:
            assert False, f"No message arrived"

Output

Reading message. {'id': 1}
Retry error: "test_product" --> No message arrived. [1/4] Retrying new execution in 2 second(s)
Reading message. {'id': 2}
Retry error: "test_product" --> No message arrived. [2/4] Retrying new execution in 2 second(s)
Reading message. {'id': 3}
Retry error: "test_product" --> No message arrived. [3/4] Retrying new execution in 2 second(s)
Reading message. {'id': 4}
Retry error: "test_product" --> No message arrived. [4/4] Retrying new execution in 2 second(s)
Reading message. {'id': 5}
FAILED
retry_helper.py:40 (Test.test_product)
self = <helpers.retry_helper.Test object at 0x0000021F2793EF28>
env = {'data': <list_iterator object at 0x0000021F2793EF60>, 'retry': 10, 'sleep': 5}

    @retry_test(stop_max_attempt_number=5, wait_fixed=2)
    def test_product(self, env):
        message_product = next(env["data"], None)
        print(f"Reading message. {message_product}")
    
        if message_product["id"] == 10:
            assert True, "Message was intercepted"
    
        else:
>           assert False, f"No message arrived"
E           AssertionError: No message arrived
E           assert False

retry_helper.py:50: AssertionError
like image 30
Dorcioman Avatar answered Oct 22 '22 01:10

Dorcioman