From 49bb5c89a6111d39455482fa415a3fd526b3b497 Mon Sep 17 00:00:00 2001 From: Virendra Patil <70162563+virendrapatil24@users.noreply.github.com> Date: Wed, 3 Jul 2024 00:28:08 +0530 Subject: [PATCH] Improved handling of invalid regex pattern in pytest.raises (#12526) --- AUTHORS | 1 + changelog/12505.bugfix.rst | 1 + src/_pytest/python_api.py | 9 +++++++++ testing/python/raises.py | 20 ++++++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 changelog/12505.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 26fa27f9b..7fd388505 100644 --- a/AUTHORS +++ b/AUTHORS @@ -430,6 +430,7 @@ Victor Rodriguez Victor Uriarte Vidar T. Fauske Vijay Arora +Virendra Patil Virgil Dupras Vitaly Lashmanov Vivaan Verma diff --git a/changelog/12505.bugfix.rst b/changelog/12505.bugfix.rst new file mode 100644 index 000000000..f55a8a17e --- /dev/null +++ b/changelog/12505.bugfix.rst @@ -0,0 +1 @@ +Improve handling of invalid regex patterns in :func:`pytest.raises(match=r'...') ` by providing a clear error message. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c1e851391..4174a55b5 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -7,6 +7,7 @@ from decimal import Decimal import math from numbers import Complex import pprint +import re from types import TracebackType from typing import Any from typing import Callable @@ -986,6 +987,14 @@ class RaisesContext(ContextManager[_pytest._code.ExceptionInfo[E]]): self.message = message self.match_expr = match_expr self.excinfo: _pytest._code.ExceptionInfo[E] | None = None + if self.match_expr is not None: + re_error = None + try: + re.compile(self.match_expr) + except re.error as e: + re_error = e + if re_error is not None: + fail(f"Invalid regex pattern provided to 'match': {re_error}") def __enter__(self) -> _pytest._code.ExceptionInfo[E]: self.excinfo = _pytest._code.ExceptionInfo.for_later() diff --git a/testing/python/raises.py b/testing/python/raises.py index 271dd3e5a..2011c8161 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -132,6 +132,26 @@ class TestRaises: result = pytester.runpytest() result.stdout.fnmatch_lines(["*2 failed*"]) + def test_raises_with_invalid_regex(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + def test_invalid_regex(): + with pytest.raises(ValueError, match="invalid regex character ["): + raise ValueError() + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*Invalid regex pattern provided to 'match': unterminated character set at position 24*", + ] + ) + result.stdout.no_fnmatch_line("*Traceback*") + result.stdout.no_fnmatch_line("*File*") + result.stdout.no_fnmatch_line("*line*") + def test_noclass(self) -> None: with pytest.raises(TypeError): pytest.raises("wrong", lambda: None) # type: ignore[call-overload]