diff --git a/AUTHORS b/AUTHORS index 1a8c5306f..86a814a13 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,6 +44,7 @@ Aron Coyle Aron Curzon Aviral Verma Aviv Palivoda +Babak Keyvani Barney Gale Ben Gartner Ben Webb diff --git a/changelog/8646.improvement.rst b/changelog/8646.improvement.rst new file mode 100644 index 000000000..9691c1434 --- /dev/null +++ b/changelog/8646.improvement.rst @@ -0,0 +1,2 @@ +Improve :py:func:`pytest.raises`. Previously passing an empty tuple would give a confusing +error. We now raise immediately with a more helpful message. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 5fa219619..bef9ec47b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -899,6 +899,12 @@ def raises( """ __tracebackhide__ = True + if not expected_exception: + raise ValueError( + f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. " + f"Raising exceptions is already understood as failing the test, so you don't need " + f"any special code to say 'this should never raise an exception'." + ) if isinstance(expected_exception, type): excepted_exceptions: Tuple[Type[E], ...] = (expected_exception,) else: diff --git a/testing/python/raises.py b/testing/python/raises.py index 112dec06c..f1f6ece4e 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -19,6 +19,16 @@ class TestRaises: excinfo = pytest.raises(ValueError, int, "hello") assert "invalid literal" in str(excinfo.value) + def test_raises_does_not_allow_none(self): + with pytest.raises(ValueError, match="Expected an exception type or"): + # We're testing that this invalid usage gives a helpful error, + # so we can ignore Mypy telling us that None is invalid. + pytest.raises(expected_exception=None) # type: ignore + + def test_raises_does_not_allow_empty_tuple(self): + with pytest.raises(ValueError, match="Expected an exception type or"): + pytest.raises(expected_exception=()) + def test_raises_callable_no_exception(self) -> None: class A: def __call__(self):