From 3444d35c540c635401f92db724d004e2a7d20920 Mon Sep 17 00:00:00 2001 From: Babak Keyvani Date: Sat, 30 Apr 2022 17:56:36 -0600 Subject: [PATCH 1/5] improve `pytest.raises` --- AUTHORS | 1 + changelog/8646.improvments.rst | 2 ++ src/_pytest/python_api.py | 7 +++++++ testing/python/raises.py | 4 ++++ 4 files changed, 14 insertions(+) create mode 100644 changelog/8646.improvments.rst 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.improvments.rst b/changelog/8646.improvments.rst new file mode 100644 index 000000000..9691c1434 --- /dev/null +++ b/changelog/8646.improvments.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..410877c88 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -899,6 +899,13 @@ def raises( """ __tracebackhide__ = True + if expected_exception == (): + raise ValueError( + "Passing expected_exception=() is an error, because it's impossible to " + "raise an exception which is not an instance of any type. Raising exceptions " + "is already understood as failing the test, so you don't need 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..e1680623a 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -19,6 +19,10 @@ class TestRaises: excinfo = pytest.raises(ValueError, int, "hello") assert "invalid literal" in str(excinfo.value) + def test_raises_does_not_allow_empty_tuple(self): + with pytest.raises(ValueError): + pytest.raises(expected_exception=()) + def test_raises_callable_no_exception(self) -> None: class A: def __call__(self): From 31a9c5c66709609f8adfa81a9e3e4bf1147e0369 Mon Sep 17 00:00:00 2001 From: Babak Keyvani Date: Mon, 9 May 2022 21:15:02 -0400 Subject: [PATCH 2/5] improve `pytest.raises` - cont'd a few more iterations on error message and related tests. --- src/_pytest/python_api.py | 9 ++++----- testing/python/raises.py | 6 +++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 410877c88..bef9ec47b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -899,12 +899,11 @@ def raises( """ __tracebackhide__ = True - if expected_exception == (): + if not expected_exception: raise ValueError( - "Passing expected_exception=() is an error, because it's impossible to " - "raise an exception which is not an instance of any type. Raising exceptions " - "is already understood as failing the test, so you don't need any special " - "code to say 'this should never raise an exception'." + 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,) diff --git a/testing/python/raises.py b/testing/python/raises.py index e1680623a..b3fa0fc0e 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -19,8 +19,12 @@ 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"): + pytest.raises(expected_exception=None) + def test_raises_does_not_allow_empty_tuple(self): - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Expected an exception type or"): pytest.raises(expected_exception=()) def test_raises_callable_no_exception(self) -> None: From 29462b1277fdae847b0527cf8e05a40c69810d39 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 10 May 2022 23:24:13 -0700 Subject: [PATCH 3/5] type-ignore in error-message test --- testing/python/raises.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testing/python/raises.py b/testing/python/raises.py index b3fa0fc0e..f1f6ece4e 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -21,7 +21,9 @@ class TestRaises: def test_raises_does_not_allow_none(self): with pytest.raises(ValueError, match="Expected an exception type or"): - pytest.raises(expected_exception=None) + # 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"): From 58af76122fe26a02f7cc3dd8178615b2c575e15c Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 10 May 2022 23:27:06 -0700 Subject: [PATCH 4/5] Move changelog file --- changelog/{8646.improvments.rst => 8646.improvment.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{8646.improvments.rst => 8646.improvment.rst} (100%) diff --git a/changelog/8646.improvments.rst b/changelog/8646.improvment.rst similarity index 100% rename from changelog/8646.improvments.rst rename to changelog/8646.improvment.rst From a29f4aff98ad019182d34965aa51ebfda11fb9ce Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 10 May 2022 23:27:33 -0700 Subject: [PATCH 5/5] Update 8646.improvement.rst --- changelog/{8646.improvment.rst => 8646.improvement.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{8646.improvment.rst => 8646.improvement.rst} (100%) diff --git a/changelog/8646.improvment.rst b/changelog/8646.improvement.rst similarity index 100% rename from changelog/8646.improvment.rst rename to changelog/8646.improvement.rst