unittest: cleanup unexpected success handling (#8231)

* unittest: cleanup unexpected success handling

* update comment
This commit is contained in:
Anton 2021-01-13 17:02:26 -08:00 committed by GitHub
parent 7a5a6cb51c
commit 42d5545f42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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)