Skip to content

pytest.raises

pytest.raises(ExceptionType) is a context manager that asserts the code inside its with block raises the given exception type. If the exception is raised, the test passes; if it isnโ€™t raised (or a different exception is raised), the test fails.

Testing that code raises correctly without a dedicated tool means manually wrapping it in try/except and asserting on the control flow yourself:

def test_divide_by_zero():
try:
divide(10, 0)
assert False, "Expected ValueError but nothing was raised"
except ValueError:
pass # this is the expected outcome
except Exception as e:
assert False, f"Expected ValueError but got {type(e)}"
import pytest
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(10, 0)
# test passes if ValueError was raised inside the block;
# fails if nothing was raised, or a different exception type was
# Capturing the exception to inspect it further
def test_divide_by_zero_message():
with pytest.raises(ValueError) as exc_info:
divide(10, 0)
assert "Cannot divide by zero" in str(exc_info.value)
# match= checks the exception message against a regex directly
def test_divide_by_zero_match():
with pytest.raises(ValueError, match="Cannot divide"):
divide(10, 0)
  • One line of clear intent: with pytest.raises(ValueError): divide(10, 0) reads as exactly what it tests, versus a multi-branch try/except/assert False block.
  • Fails correctly on the right conditions: no exception raised, or the wrong exception type raised, both correctly fail the test โ€” a hand-rolled try/except ValueError: pass alone wouldnโ€™t catch โ€œnothing was raised at allโ€ without the extra assert False in the try body.
  • exc_info and match=: built-in ways to assert on the exceptionโ€™s message or attributes, not just its type.
  • Code after the raising line inside the with block never runs โ€” once the exception fires, control jumps straight to pytest.raisesโ€™s handling, same as a normal except.
  • match= takes a regex pattern, checked with re.search against str(exception) โ€” special regex characters in the expected message need escaping if you want a literal match.
  • If you expect no exception, you simply donโ€™t wrap the call in pytest.raises at all โ€” an unexpected exception during a normal test already fails it.
  • pytest.raises(ValueError) also matches subclasses of ValueError, following normal Python exception-matching rules (same as except ValueError).
  1. What happens if the code inside with pytest.raises(ValueError): ... doesnโ€™t raise anything?

    AnswerThe test fails โ€” `pytest.raises` requires the specified exception to actually be raised.
  2. How do you also check the exceptionโ€™s message, not just its type?

    AnswerEither `pytest.raises(ValueError, match="expected text")` (regex match against the message) or capture `as exc_info` and assert on `str(exc_info.value)`.
  3. If the code raises TypeError but the test expects pytest.raises(ValueError), does the test pass?

    AnswerNo โ€” it fails, because the raised exception type doesn't match (unless `TypeError` were a subclass of `ValueError`, which it isn't).