pytest Failed: DID NOT RAISE (tested)
Failed: DID NOT RAISE <Exception> means the code inside with pytest.raises(...) finished without raising. AssertionError: Regex pattern did not match means it raised, but match= (a regex) did not match the message; use re.escape() for messages with parentheses or dots.
1. The test file
import pytest
def parse_age(s):
age = int(s) # ValueError for "abc"
if age < 0:
raise ValueError(f"age must be >= 0, got {age}")
return age
def test_did_not_raise():
with pytest.raises(ValueError):
parse_age("42") # valid input: nothing raised
def test_wrong_type():
with pytest.raises(TypeError):
parse_age("abc") # raises ValueError, not TypeError
def test_match_fails():
with pytest.raises(ValueError, match="must be positive"):
parse_age("-1")
def test_match_special_chars():
with pytest.raises(ValueError, match="age must be >= 0, got -1 (negative)"):
raise ValueError("age must be >= 0, got -1 (negative)")
def test_code_after_raise_never_runs():
with pytest.raises(ValueError) as excinfo:
parse_age("-1")
assert False, "never reached" # skipped: the line above raised
assert "got -1" in str(excinfo.value)
def test_match_escaped():
import re
msg = "age must be >= 0, got -1 (negative)"
with pytest.raises(ValueError, match=re.escape(msg)):
raise ValueError(msg)
Output (filtered to the headers and E lines):
$ pytest -rA test_raises.py | grep -E "^(PASSED|FAILED)|^E |^_"
______________________________ test_did_not_raise ______________________________
E Failed: DID NOT RAISE ValueError
_______________________________ test_wrong_type ________________________________
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
E ValueError: invalid literal for int() with base 10: 'abc'
_______________________________ test_match_fails _______________________________
E AssertionError: Regex pattern did not match.
E Expected regex: 'must be positive'
E Actual message: 'age must be >= 0, got -1'
___________________________ test_match_special_chars ___________________________
E AssertionError: Regex pattern did not match.
E Expected regex: 'age must be >= 0, got -1 (negative)'
E Actual message: 'age must be >= 0, got -1 (negative)'
E Did you mean to `re.escape()` the regex?
PASSED test_raises.py::test_code_after_raise_never_runs
PASSED test_raises.py::test_match_escaped
FAILED test_raises.py::test_did_not_raise - Failed: DID NOT RAISE ValueError
FAILED test_raises.py::test_wrong_type - ValueError: invalid literal for int(...
FAILED test_raises.py::test_match_fails - AssertionError: Regex pattern did n...
FAILED test_raises.py::test_match_special_chars - AssertionError: Regex patte...
2. "Failed: DID NOT RAISE ValueError"
pytest.raises(X) fails with DID NOT RAISE when the code inside the with block finishes without raising anything. Either the input does not trigger the error (here "42" is valid), or the code raises somewhere else: before the with block (then the test fails with that real exception instead) or not at all because the check you expect does not exist. Print or debug the call outside pytest.raises to see what it actually returns.
3. A different exception is not caught
If the code raises another type than the one you expect (ValueError instead of TypeError), pytest.raises does not catch it: the test fails with the original exception and its traceback, which is usually the quickest way to see what really happened. Subclasses do match, so pytest.raises(Exception) catches nearly everything, which is why it is a weak test.
4. "Regex pattern did not match"
match= is a regular expression searched in str(exception) with re.search. pytest prints the expected regex and the actual message side by side. In test_match_special_chars they look identical, but ( and ) are regex groups, so the pattern does not match the literal parentheses; pytest itself suggests re.escape(), and test_match_escaped passes with it. Escape any message that contains ( ) [ ] . * + ? $ ^ | or a backslash.
5. Code after the raising line never runs
Inside the with pytest.raises(...) block, everything after the line that raises is skipped (the assert False in test_code_after_raise_never_runs never ran). Put only the one call that should raise inside the block, and check the exception afterwards through excinfo.value.
Related: pytest error vs failure, pytest ERROR collecting: ModuleNotFoundError.
Frequently asked questions
What does Failed: DID NOT RAISE mean in pytest?
The code inside the pytest.raises block completed without raising the expected exception (or any exception).
Why does pytest.raises match fail when the messages look identical?
match= is a regular expression; characters like ( ) . + are special. Wrap the expected message in re.escape().
Written with AI assistance. Measured on 2026-10-23 with pytest 9.1.1 and Python 3.13.5 on Linux. The test file was run verbatim and the output pasted unedited (filtered by the grep shown). PlainHeaders is our extension; Python and pytest are free.