diff --git a/AUTHORS b/AUTHORS index c33cf5fafbd..d6d2737a4bf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -180,6 +180,7 @@ Fraser Stark Freya Bruhin Gabriel Landau Gabriel Reis +Garion Milazzo Garvit Shubham Gene Wood George Kussumoto diff --git a/changelog/14389.bugfix.rst b/changelog/14389.bugfix.rst new file mode 100644 index 00000000000..15bccc5bbce --- /dev/null +++ b/changelog/14389.bugfix.rst @@ -0,0 +1 @@ +Improved ``pytest.raises(..., match=...)`` failures to report the mismatched exception as the direct cause of the resulting ``AssertionError``. diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 82fe2c41c96..d24eddb014a 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -698,7 +698,7 @@ def __exit__( if not self.matches(exc_val): if self._just_propagate: return False - raise AssertionError(self._fail_reason) + raise AssertionError(self._fail_reason) from exc_val # Cast to narrow the exception type now that it's verified.... # even though the TypeGuard in self.matches should be narrowing diff --git a/testing/python/raises.py b/testing/python/raises.py index f74d747c0df..70234ddcfb6 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -179,6 +179,29 @@ def test_invalid_regex(): result.stdout.no_fnmatch_line("*File*") result.stdout.no_fnmatch_line("*line*") + def test_raises_match_failure_uses_direct_cause(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + def test_raises_match_failure(): + with pytest.raises(ValueError, match="expected"): + raise ValueError("actual") + """ + ) + result = pytester.runpytest("--tb=short") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*ValueError: actual", + "*The above exception was the direct cause of the following exception:*", + "*E*AssertionError: Regex pattern did not match.*", + ] + ) + result.stdout.no_fnmatch_line( + "*During handling of the above exception, another exception occurred:*" + ) + def test_noclass(self) -> None: with pytest.raises(TypeError): with pytest.raises("wrong"): # type: ignore[call-overload]