pytest-dev / pytest-rerunfailures

a pytest plugin that re-runs failed tests up to -n times to eliminate flakey failures
Other
369 stars 82 forks source link

Session and class scope fixtures won't teardown when specifying only_rerun or rerun_except #234

Closed sd148684 closed 4 months ago

sd148684 commented 10 months ago

Given two fixtures like this:

import pytest
@pytest.fixture(scope="session")
def session_fixture():
    print("session setup")
    yield "session"
    print("session teardown")

@pytest.fixture
def function_fixture():
    print("function setup")
    yield "function"
    print("function teardown")

Create and run a test function with pytest.mark.flaky and rerun_except:

@pytest.mark.flaky(reruns=3, rerun_except="AssertionError")
def test_no_teardown(session_fixture, function_fixture):
    print("run test_rerun_no_teardown")
    assert False, "fake false assertion"

The session teardown was missing in outputs (regular pytest outputs are omitted).

$ pytest tests.py::test_no_teardown -vvs
session setup
function setup
run test_rerun_teardown
FAILED
function teardown

The same issue occurs with only_rerun.

@pytest.mark.flaky(reruns=3, only_rerun=["RuntimeError"])
def test_no_teardown(session_fixture, function_fixture):
    print("run test_rerun_no_teardown")
    assert False, "fake false assertion"

And the same issue occurs without pytest.mark.flaky mark but run with command arguments.

# run with pytest --rerun 3 --rerun-except assert
# or pytest --rerun 3 --rerun-only RuntimeError
def test_no_teardown(session_fixture, function_fixture):
    print("run test_rerun_no_teardown")
    assert False, "fake false assertion"

Class scope fixture won't teardown either:

@pytest.fixture(scope="class")
def class_fixture():
    print("class setup")
    yield "class"
    print("class teardown")

class TestClass:
    @pytest.mark.flaky(rerun=3, rerun_except="AssertionError")
    def test_no_teardown_class(self, session_fixture, class_fixture, function_fixture):
        print("run test_no_teardown_class")
        assert False, "fake false assertion"
        # no "class teardown" and "session teardown" in outputs

Session and class fixtures DO teardown normally on those tests:

def test_will_teardown(session_fixture, function_fixture):
    """ no flaky mark """
    print("run test_will_teardown")
    assert False, "fake false assertion"

@pytest.mark.flaky(reruns=3)
def test_will_teardown_1(session_fixture, function_fixture):
    """ neither only_rerun nor rerun_except specified """
    print("run test_will_teardown_1")
    assert False, "fake false assertion"

@pytest.mark.flaky(rerun=3, rerun_except="AssertionError")
def test_will_teardown_2(session_fixture, function_fixture):
    """ passed test with only_rerun or rerun_except specified """
    print("run test_will_teardown_2")

Output below, session fixture teardown normally.

$ pytest tests.py::test_will_teardown -vvs
session setup
function setup
run test_will_teardown
FAILED
function teardown
session teardown

Tested with a fresh new venv(Python 3.11), pytest==7.4.0, pytest-rerunfailures=12.0 .

sd148684 commented 10 months ago

Update: tested with pytest-rerunfailures==11.1.2, session/class fixtures teardown successfully. But rerun strategy seems broken, test was re-run 3 times despite of only_rerun or rerun_except settings (possibly related to #225 ).