Skip to content

Commit 9db1823

Browse files
committed
Improve type-checking in OutcomeException
Fix #5578
1 parent 2180d9e commit 9db1823

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

changelog/5578.bugfix.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve type checking for some exception-raising functions (``pytest.xfail``, ``pytest.skip``, etc)
2+
so they provide better error messages when users meant to use marks (for example ``@pytest.xfail``
3+
instead of ``@pytest.mark.xfail``).

src/_pytest/outcomes.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ class OutcomeException(BaseException):
1313
"""
1414

1515
def __init__(self, msg=None, pytrace=True):
16+
if msg is not None and not isinstance(msg, str):
17+
error_msg = (
18+
"{} expected string as 'msg' parameter, got '{}' instead.\n"
19+
"Perhaps you meant to use a mark?"
20+
)
21+
raise TypeError(error_msg.format(type(self).__name__, type(msg).__name__))
1622
BaseException.__init__(self, msg)
1723
self.msg = msg
1824
self.pytrace = pytrace
1925

2026
def __repr__(self):
2127
if self.msg:
22-
val = self.msg
23-
if isinstance(val, bytes):
24-
val = val.decode("UTF-8", errors="replace")
25-
return val
28+
return self.msg
2629
return "<{} instance>".format(self.__class__.__name__)
2730

2831
__str__ = __repr__

testing/test_runner.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from _pytest import outcomes
1212
from _pytest import reports
1313
from _pytest import runner
14+
from _pytest.outcomes import OutcomeException
1415

1516

1617
class TestSetupState:
@@ -990,3 +991,18 @@ def test_func():
990991
rep = reports[1]
991992
assert rep.capstdout == ""
992993
assert rep.capstderr == ""
994+
995+
996+
def test_outcome_exception_bad_msg():
997+
"""Check that OutcomeExceptions validate their input to prevent confusing errors (#5578)"""
998+
999+
def func():
1000+
pass
1001+
1002+
expected = (
1003+
"OutcomeException expected string as 'msg' parameter, got 'function' instead.\n"
1004+
"Perhaps you meant to use a mark?"
1005+
)
1006+
with pytest.raises(TypeError) as excinfo:
1007+
OutcomeException(func)
1008+
assert str(excinfo.value) == expected

testing/test_skipping.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,8 @@ def test_module_level_skip_error(testdir):
10661066
testdir.makepyfile(
10671067
"""
10681068
import pytest
1069-
@pytest.skip
1069+
pytest.skip("skip_module_level")
1070+
10701071
def test_func():
10711072
assert True
10721073
"""

0 commit comments

Comments
 (0)