unittest: cleanup unexpected success handling (#8231)
* unittest: cleanup unexpected success handling * update comment
This commit is contained in:
parent
7a5a6cb51c
commit
42d5545f42
|
@ -234,7 +234,6 @@ def evaluate_xfail_marks(item: Item) -> Optional[Xfail]:
|
||||||
skipped_by_mark_key = StoreKey[bool]()
|
skipped_by_mark_key = StoreKey[bool]()
|
||||||
# Saves the xfail mark evaluation. Can be refreshed during call if None.
|
# Saves the xfail mark evaluation. Can be refreshed during call if None.
|
||||||
xfailed_key = StoreKey[Optional[Xfail]]()
|
xfailed_key = StoreKey[Optional[Xfail]]()
|
||||||
unexpectedsuccess_key = StoreKey[str]()
|
|
||||||
|
|
||||||
|
|
||||||
@hookimpl(tryfirst=True)
|
@hookimpl(tryfirst=True)
|
||||||
|
@ -271,15 +270,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
rep = outcome.get_result()
|
rep = outcome.get_result()
|
||||||
xfailed = item._store.get(xfailed_key, None)
|
xfailed = item._store.get(xfailed_key, None)
|
||||||
# unittest special case, see setting of unexpectedsuccess_key
|
if item.config.option.runxfail:
|
||||||
if unexpectedsuccess_key in item._store and rep.when == "call":
|
|
||||||
reason = item._store[unexpectedsuccess_key]
|
|
||||||
if reason:
|
|
||||||
rep.longrepr = f"Unexpected success: {reason}"
|
|
||||||
else:
|
|
||||||
rep.longrepr = "Unexpected success"
|
|
||||||
rep.outcome = "failed"
|
|
||||||
elif item.config.option.runxfail:
|
|
||||||
pass # don't interfere
|
pass # don't interfere
|
||||||
elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception):
|
elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception):
|
||||||
assert call.excinfo.value.msg is not None
|
assert call.excinfo.value.msg is not None
|
||||||
|
|
|
@ -30,10 +30,10 @@ from _pytest.python import Function
|
||||||
from _pytest.python import PyCollector
|
from _pytest.python import PyCollector
|
||||||
from _pytest.runner import CallInfo
|
from _pytest.runner import CallInfo
|
||||||
from _pytest.skipping import skipped_by_mark_key
|
from _pytest.skipping import skipped_by_mark_key
|
||||||
from _pytest.skipping import unexpectedsuccess_key
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import unittest
|
import unittest
|
||||||
|
import twisted.trial.unittest
|
||||||
|
|
||||||
from _pytest.fixtures import _Scope
|
from _pytest.fixtures import _Scope
|
||||||
|
|
||||||
|
@ -273,9 +273,18 @@ class TestCaseFunction(Function):
|
||||||
self._addexcinfo(sys.exc_info())
|
self._addexcinfo(sys.exc_info())
|
||||||
|
|
||||||
def addUnexpectedSuccess(
|
def addUnexpectedSuccess(
|
||||||
self, testcase: "unittest.TestCase", reason: str = ""
|
self,
|
||||||
|
testcase: "unittest.TestCase",
|
||||||
|
reason: Optional["twisted.trial.unittest.Todo"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._store[unexpectedsuccess_key] = reason
|
msg = "Unexpected success"
|
||||||
|
if reason:
|
||||||
|
msg += f": {reason.reason}"
|
||||||
|
# Preserve unittest behaviour - fail the test. Explicitly not an XPASS.
|
||||||
|
try:
|
||||||
|
fail(msg, pytrace=False)
|
||||||
|
except fail.Exception:
|
||||||
|
self._addexcinfo(sys.exc_info())
|
||||||
|
|
||||||
def addSuccess(self, testcase: "unittest.TestCase") -> None:
|
def addSuccess(self, testcase: "unittest.TestCase") -> None:
|
||||||
pass
|
pass
|
||||||
|
@ -283,15 +292,6 @@ class TestCaseFunction(Function):
|
||||||
def stopTest(self, testcase: "unittest.TestCase") -> None:
|
def stopTest(self, testcase: "unittest.TestCase") -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _expecting_failure(self, test_method) -> bool:
|
|
||||||
"""Return True if the given unittest method (or the entire class) is marked
|
|
||||||
with @expectedFailure."""
|
|
||||||
expecting_failure_method = getattr(
|
|
||||||
test_method, "__unittest_expecting_failure__", False
|
|
||||||
)
|
|
||||||
expecting_failure_class = getattr(self, "__unittest_expecting_failure__", False)
|
|
||||||
return bool(expecting_failure_class or expecting_failure_method)
|
|
||||||
|
|
||||||
def runtest(self) -> None:
|
def runtest(self) -> None:
|
||||||
from _pytest.debugging import maybe_wrap_pytest_function_for_tracing
|
from _pytest.debugging import maybe_wrap_pytest_function_for_tracing
|
||||||
|
|
||||||
|
|
|
@ -765,7 +765,8 @@ def test_unittest_expected_failure_for_failing_test_is_xfail(
|
||||||
|
|
||||||
@pytest.mark.parametrize("runner", ["pytest", "unittest"])
|
@pytest.mark.parametrize("runner", ["pytest", "unittest"])
|
||||||
def test_unittest_expected_failure_for_passing_test_is_fail(
|
def test_unittest_expected_failure_for_passing_test_is_fail(
|
||||||
pytester: Pytester, runner
|
pytester: Pytester,
|
||||||
|
runner: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
script = pytester.makepyfile(
|
script = pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -782,7 +783,11 @@ def test_unittest_expected_failure_for_passing_test_is_fail(
|
||||||
if runner == "pytest":
|
if runner == "pytest":
|
||||||
result = pytester.runpytest("-rxX")
|
result = pytester.runpytest("-rxX")
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
["*MyTestCase*test_passing_test_is_fail*", "*1 failed*"]
|
[
|
||||||
|
"*MyTestCase*test_passing_test_is_fail*",
|
||||||
|
"Unexpected success",
|
||||||
|
"*1 failed*",
|
||||||
|
]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
result = pytester.runpython(script)
|
result = pytester.runpython(script)
|
||||||
|
|
Loading…
Reference in New Issue