assertion: save/restore hooks on item (#6646)
This commit is contained in:
parent
1480aa31a7
commit
aa0328782f
|
@ -0,0 +1 @@
|
|||
Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <_pytest.pytester.Testdir.runpytest>` etc.
|
|
@ -8,6 +8,7 @@ from _pytest.assertion import rewrite
|
|||
from _pytest.assertion import truncate
|
||||
from _pytest.assertion import util
|
||||
from _pytest.compat import TYPE_CHECKING
|
||||
from _pytest.config import hookimpl
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.main import Session
|
||||
|
@ -105,7 +106,8 @@ def pytest_collection(session: "Session") -> None:
|
|||
assertstate.hook.set_session(session)
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
@hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_protocol(item):
|
||||
"""Setup the pytest_assertrepr_compare and pytest_assertion_pass hooks
|
||||
|
||||
The newinterpret and rewrite modules will use util._reprcompare if
|
||||
|
@ -143,6 +145,7 @@ def pytest_runtest_setup(item):
|
|||
return res
|
||||
return None
|
||||
|
||||
saved_assert_hooks = util._reprcompare, util._assertion_pass
|
||||
util._reprcompare = callbinrepr
|
||||
|
||||
if item.ihook.pytest_assertion_pass.get_hookimpls():
|
||||
|
@ -154,10 +157,9 @@ def pytest_runtest_setup(item):
|
|||
|
||||
util._assertion_pass = call_assertion_pass_hook
|
||||
|
||||
yield
|
||||
|
||||
def pytest_runtest_teardown(item):
|
||||
util._reprcompare = None
|
||||
util._assertion_pass = None
|
||||
util._reprcompare, util._assertion_pass = saved_assert_hooks
|
||||
|
||||
|
||||
def pytest_sessionfinish(session):
|
||||
|
|
|
@ -27,7 +27,6 @@ from pluggy import HookspecMarker
|
|||
from pluggy import PluginManager
|
||||
|
||||
import _pytest._code
|
||||
import _pytest.assertion
|
||||
import _pytest.deprecated
|
||||
import _pytest.hookspec # the extension point definitions
|
||||
from .exceptions import PrintHelp
|
||||
|
@ -260,6 +259,8 @@ class PytestPluginManager(PluginManager):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
import _pytest.assertion
|
||||
|
||||
super().__init__("pytest")
|
||||
# The objects are module objects, only used generically.
|
||||
self._conftest_plugins = set() # type: Set[object]
|
||||
|
@ -891,6 +892,8 @@ class Config:
|
|||
ns, unknown_args = self._parser.parse_known_and_unknown_args(args)
|
||||
mode = getattr(ns, "assertmode", "plain")
|
||||
if mode == "rewrite":
|
||||
import _pytest.assertion
|
||||
|
||||
try:
|
||||
hook = _pytest.assertion.install_importhook(self)
|
||||
except SystemError:
|
||||
|
|
|
@ -72,10 +72,19 @@ class TestImportHookInstallation:
|
|||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"E * AssertionError: ([[][]], [[][]], [[]<TestReport *>[]])*",
|
||||
"E * assert"
|
||||
" {'failed': 1, 'passed': 0, 'skipped': 0} =="
|
||||
" {'failed': 0, 'passed': 1, 'skipped': 0}",
|
||||
"> r.assertoutcome(passed=1)",
|
||||
"E AssertionError: ([[][]], [[][]], [[]<TestReport *>[]])*",
|
||||
"E assert {'failed': 1,... 'skipped': 0} == {'failed': 0,... 'skipped': 0}",
|
||||
"E Omitting 1 identical items, use -vv to show",
|
||||
"E Differing items:",
|
||||
"E Use -v to get the full diff",
|
||||
]
|
||||
)
|
||||
# XXX: unstable output.
|
||||
result.stdout.fnmatch_lines_random(
|
||||
[
|
||||
"E {'failed': 1} != {'failed': 0}",
|
||||
"E {'passed': 0} != {'passed': 1}",
|
||||
]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue