add exception spec to pytest_fixture_post_finalizer hook
This commit is contained in:
parent
1f001cd105
commit
5df7641107
|
@ -1023,17 +1023,23 @@ class FixtureDef(Generic[FixtureValue]):
|
|||
except BaseException as e:
|
||||
exceptions.append(e)
|
||||
node = request.node
|
||||
node.ihook.pytest_fixture_post_finalizer(fixturedef=self, request=request)
|
||||
if len(exceptions) == 1:
|
||||
final_exception = exceptions[0]
|
||||
elif len(exceptions) > 1:
|
||||
msg = f'errors while tearing down fixture "{self.argname}" of {node}'
|
||||
final_exception = BaseExceptionGroup(msg, exceptions[::-1])
|
||||
else:
|
||||
final_exception = None
|
||||
node.ihook.pytest_fixture_post_finalizer(
|
||||
fixturedef=self, request=request, exception=final_exception
|
||||
)
|
||||
# Even if finalization fails, we invalidate the cached fixture
|
||||
# value and remove all finalizers because they may be bound methods
|
||||
# which will keep instances alive.
|
||||
self.cached_result = None
|
||||
self._finalizers.clear()
|
||||
if len(exceptions) == 1:
|
||||
raise exceptions[0]
|
||||
elif len(exceptions) > 1:
|
||||
msg = f'errors while tearing down fixture "{self.argname}" of {node}'
|
||||
raise BaseExceptionGroup(msg, exceptions[::-1])
|
||||
if final_exception:
|
||||
raise final_exception
|
||||
|
||||
def execute(self, request: SubRequest) -> FixtureValue:
|
||||
"""Return the value of this fixture, executing it if not cached."""
|
||||
|
|
|
@ -861,7 +861,9 @@ def pytest_fixture_setup(
|
|||
|
||||
|
||||
def pytest_fixture_post_finalizer(
|
||||
fixturedef: "FixtureDef[Any]", request: "SubRequest"
|
||||
fixturedef: "FixtureDef[Any]",
|
||||
request: "SubRequest",
|
||||
exception: "BaseException | None",
|
||||
) -> None:
|
||||
"""Called after fixture teardown, but before the cache is cleared, so
|
||||
the fixture result ``fixturedef.cached_result`` is still available (not
|
||||
|
@ -871,6 +873,8 @@ def pytest_fixture_post_finalizer(
|
|||
The fixture definition object.
|
||||
:param request:
|
||||
The fixture request object.
|
||||
:param exception:
|
||||
The list of exceptions received at the end of the fixtures.
|
||||
|
||||
Use in conftest plugins
|
||||
=======================
|
||||
|
|
|
@ -4014,6 +4014,63 @@ def test_pytest_fixture_setup_and_post_finalizer_hook(pytester: Pytester) -> Non
|
|||
)
|
||||
|
||||
|
||||
def test_exceptions_in_pytest_fixture_setup_and_post_finalizer_hook(
|
||||
pytester: Pytester,
|
||||
) -> None:
|
||||
pytester.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_fixture_setup(fixturedef):
|
||||
result = yield
|
||||
print('SETUP EXCEPTION in {0}: {1}'.format(fixturedef.argname, result.exception))
|
||||
def pytest_fixture_post_finalizer(fixturedef, exception):
|
||||
print('TEARDOWN EXCEPTION in {0}: {1}'.format(fixturedef.argname, exception))
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
**{
|
||||
"tests/test_fixture_exceptions.py": """
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def module_teardown_exeption():
|
||||
yield
|
||||
raise ValueError('exeption in module_teardown_exeption')
|
||||
|
||||
@pytest.fixture()
|
||||
def func_teardown_exeption():
|
||||
yield
|
||||
raise ValueError('exeption in func_teardown_exeption')
|
||||
|
||||
@pytest.fixture()
|
||||
def func_setup_exeption():
|
||||
raise ValueError('exeption in func_setup_exeption')
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
'module_teardown_exeption',
|
||||
'func_teardown_exeption',
|
||||
'func_setup_exeption',
|
||||
)
|
||||
def test_func():
|
||||
pass
|
||||
""",
|
||||
}
|
||||
)
|
||||
result = pytester.runpytest("-s")
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*SETUP EXCEPTION in module_teardown_exeption: None*",
|
||||
"*SETUP EXCEPTION in func_teardown_exeption: None*",
|
||||
"*SETUP EXCEPTION in func_setup_exeption: exeption in func_setup_exeption*",
|
||||
"*TEARDOWN EXCEPTION in func_setup_exeption: None*",
|
||||
"*TEARDOWN EXCEPTION in func_teardown_exeption: exeption in func_teardown_exeption*",
|
||||
"*TEARDOWN EXCEPTION in module_teardown_exeption: exeption in module_teardown_exeption*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestScopeOrdering:
|
||||
"""Class of tests that ensure fixtures are ordered based on their scopes (#2405)"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue