pytester: split asserts to a separate plugin, don't rewrite pytester itself
An upcoming commit wants to import from `_pytest.pytester` in the public `pytest` module. This means that `_pytest.pytester` would start to get imported during import time, which it hasn't up to now -- it was imported by the plugin loader (if requested). When a plugin is loaded, it is subjected to assertion rewriting, but only if the module isn't imported yet, it issues a warning "Module already imported so cannot be rewritten" and skips the rewriting. So we'd end up with the pytester plugin not being rewritten, but it wants to be. Absent better ideas, the solution here is to split the pytester assertions to their own plugin (which will always only be imported by the plugin loader) and exclude pytester itself from plugin rewriting.
This commit is contained in:
parent
e986d84466
commit
b050578882
|
@ -256,6 +256,7 @@ default_plugins = essential_plugins + (
|
|||
|
||||
builtin_plugins = set(default_plugins)
|
||||
builtin_plugins.add("pytester")
|
||||
builtin_plugins.add("pytester_assertions")
|
||||
|
||||
|
||||
def get_config(
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
"""(Disabled by default) support for testing pytest and pytest plugins."""
|
||||
"""(Disabled by default) support for testing pytest and pytest plugins.
|
||||
|
||||
PYTEST_DONT_REWRITE
|
||||
"""
|
||||
import collections.abc
|
||||
import contextlib
|
||||
import gc
|
||||
|
@ -66,6 +69,9 @@ if TYPE_CHECKING:
|
|||
import pexpect
|
||||
|
||||
|
||||
pytest_plugins = ["pytester_assertions"]
|
||||
|
||||
|
||||
IGNORE_PAM = [ # filenames added when obtaining details about the current user
|
||||
"/var/lib/sss/mc/passwd"
|
||||
]
|
||||
|
@ -408,16 +414,12 @@ class HookRecorder:
|
|||
|
||||
def assertoutcome(self, passed: int = 0, skipped: int = 0, failed: int = 0) -> None:
|
||||
__tracebackhide__ = True
|
||||
from _pytest.pytester_assertions import assertoutcome
|
||||
|
||||
outcomes = self.listoutcomes()
|
||||
realpassed, realskipped, realfailed = outcomes
|
||||
obtained = {
|
||||
"passed": len(realpassed),
|
||||
"skipped": len(realskipped),
|
||||
"failed": len(realfailed),
|
||||
}
|
||||
expected = {"passed": passed, "skipped": skipped, "failed": failed}
|
||||
assert obtained == expected, outcomes
|
||||
assertoutcome(
|
||||
outcomes, passed=passed, skipped=skipped, failed=failed,
|
||||
)
|
||||
|
||||
def clear(self) -> None:
|
||||
self.calls[:] = []
|
||||
|
@ -574,25 +576,18 @@ class RunResult:
|
|||
"""Assert that the specified outcomes appear with the respective
|
||||
numbers (0 means it didn't occur) in the text output from a test run."""
|
||||
__tracebackhide__ = True
|
||||
from _pytest.pytester_assertions import assert_outcomes
|
||||
|
||||
d = self.parseoutcomes()
|
||||
obtained = {
|
||||
"passed": d.get("passed", 0),
|
||||
"skipped": d.get("skipped", 0),
|
||||
"failed": d.get("failed", 0),
|
||||
"errors": d.get("errors", 0),
|
||||
"xpassed": d.get("xpassed", 0),
|
||||
"xfailed": d.get("xfailed", 0),
|
||||
}
|
||||
expected = {
|
||||
"passed": passed,
|
||||
"skipped": skipped,
|
||||
"failed": failed,
|
||||
"errors": errors,
|
||||
"xpassed": xpassed,
|
||||
"xfailed": xfailed,
|
||||
}
|
||||
assert obtained == expected
|
||||
outcomes = self.parseoutcomes()
|
||||
assert_outcomes(
|
||||
outcomes,
|
||||
passed=passed,
|
||||
skipped=skipped,
|
||||
failed=failed,
|
||||
errors=errors,
|
||||
xpassed=xpassed,
|
||||
xfailed=xfailed,
|
||||
)
|
||||
|
||||
|
||||
class CwdSnapshot:
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
"""Helper plugin for pytester; should not be loaded on its own."""
|
||||
# This plugin contains assertions used by pytester. pytester cannot
|
||||
# contain them itself, since it is imported by the `pytest` module,
|
||||
# hence cannot be subject to assertion rewriting, which requires a
|
||||
# module to not be already imported.
|
||||
from typing import Dict
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
from _pytest.reports import CollectReport
|
||||
from _pytest.reports import TestReport
|
||||
|
||||
|
||||
def assertoutcome(
|
||||
outcomes: Tuple[
|
||||
Sequence[TestReport],
|
||||
Sequence[Union[CollectReport, TestReport]],
|
||||
Sequence[Union[CollectReport, TestReport]],
|
||||
],
|
||||
passed: int = 0,
|
||||
skipped: int = 0,
|
||||
failed: int = 0,
|
||||
) -> None:
|
||||
__tracebackhide__ = True
|
||||
|
||||
realpassed, realskipped, realfailed = outcomes
|
||||
obtained = {
|
||||
"passed": len(realpassed),
|
||||
"skipped": len(realskipped),
|
||||
"failed": len(realfailed),
|
||||
}
|
||||
expected = {"passed": passed, "skipped": skipped, "failed": failed}
|
||||
assert obtained == expected, outcomes
|
||||
|
||||
|
||||
def assert_outcomes(
|
||||
outcomes: Dict[str, int],
|
||||
passed: int = 0,
|
||||
skipped: int = 0,
|
||||
failed: int = 0,
|
||||
errors: int = 0,
|
||||
xpassed: int = 0,
|
||||
xfailed: int = 0,
|
||||
) -> None:
|
||||
"""Assert that the specified outcomes appear with the respective
|
||||
numbers (0 means it didn't occur) in the text output from a test run."""
|
||||
__tracebackhide__ = True
|
||||
|
||||
obtained = {
|
||||
"passed": outcomes.get("passed", 0),
|
||||
"skipped": outcomes.get("skipped", 0),
|
||||
"failed": outcomes.get("failed", 0),
|
||||
"errors": outcomes.get("errors", 0),
|
||||
"xpassed": outcomes.get("xpassed", 0),
|
||||
"xfailed": outcomes.get("xfailed", 0),
|
||||
}
|
||||
expected = {
|
||||
"passed": passed,
|
||||
"skipped": skipped,
|
||||
"failed": failed,
|
||||
"errors": errors,
|
||||
"xpassed": xpassed,
|
||||
"xfailed": xfailed,
|
||||
}
|
||||
assert obtained == expected
|
Loading…
Reference in New Issue