@@ -461,21 +461,49 @@ an ``incremental`` marker which is to be used on classes:
461461
462462 # content of conftest.py
463463
464- import pytest
464+ # store history of failures per test class name and per index in parametrize (if parametrize used)
465+ _test_failed_incremental: Dict[str , Dict[Tuple[int , ... ], str ]] = {}
465466
466467
467468 def pytest_runtest_makereport (item , call ):
468469 if " incremental" in item.keywords:
470+ # incremental marker is used
469471 if call.excinfo is not None :
470- parent = item.parent
471- parent._previousfailed = item
472+ # the test has failed
473+ # retrieve the class name of the test
474+ cls_name = str (item.cls)
475+ # retrieve the index of the test (if parametrize is used in combination with incremental)
476+ parametrize_index = (
477+ tuple (item.callspec.indices.values())
478+ if hasattr (item, " callspec" )
479+ else ()
480+ )
481+ # retrieve the name of the test function
482+ test_name = item.originalname or item.name
483+ # store in _test_failed_incremental the original name of the failed test
484+ _test_failed_incremental.setdefault(cls_name, {}).setdefault(
485+ parametrize_index, test_name
486+ )
472487
473488
474489 def pytest_runtest_setup (item ):
475490 if " incremental" in item.keywords:
476- previousfailed = getattr (item.parent, " _previousfailed" , None )
477- if previousfailed is not None :
478- pytest.xfail(" previous test failed ({} )" .format(previousfailed.name))
491+ # retrieve the class name of the test
492+ cls_name = str (item.cls)
493+ # check if a previous test has failed for this class
494+ if cls_name in _test_failed_incremental:
495+ # retrieve the index of the test (if parametrize is used in combination with incremental)
496+ parametrize_index = (
497+ tuple (item.callspec.indices.values())
498+ if hasattr (item, " callspec" )
499+ else ()
500+ )
501+ # retrieve the name of the first test function to fail for this class name and index
502+ test_name = _test_failed_incremental[cls_name].get(parametrize_index, None )
503+ # if name found, test has failed for the combination of class name & test name
504+ if test_name is not None :
505+ pytest.xfail(" previous test failed ({} )" .format(test_name))
506+
479507
480508 These two hook implementations work together to abort incremental-marked
481509tests in a class. Here is a test module example:
0 commit comments