pytest.raises
pytest.raises
Section titled โpytest.raisesโWhat it is
Section titled โWhat it isโ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.
Before this feature
Section titled โBefore this featureโ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)}"After this feature
Section titled โAfter this featureโ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 furtherdef 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 directlydef test_divide_by_zero_match(): with pytest.raises(ValueError, match="Cannot divide"): divide(10, 0)Why this is better
Section titled โWhy this is betterโ- One line of clear intent:
with pytest.raises(ValueError): divide(10, 0)reads as exactly what it tests, versus a multi-branchtry/except/assert Falseblock. - 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: passalone wouldnโt catch โnothing was raised at allโ without the extraassert Falsein thetrybody. exc_infoandmatch=: built-in ways to assert on the exceptionโs message or attributes, not just its type.
Key notes / edge cases
Section titled โKey notes / edge casesโ- Code after the raising line inside the
withblock never runs โ once the exception fires, control jumps straight topytest.raisesโs handling, same as a normalexcept. match=takes a regex pattern, checked withre.searchagainststr(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.raisesat all โ an unexpected exception during a normal test already fails it. pytest.raises(ValueError)also matches subclasses ofValueError, following normal Python exception-matching rules (same asexcept ValueError).
Quick practice
Section titled โQuick practiceโ-
What happens if the code inside
with pytest.raises(ValueError): ...doesnโt raise anything?Answer
The test fails โ `pytest.raises` requires the specified exception to actually be raised. -
How do you also check the exceptionโs message, not just its type?
Answer
Either `pytest.raises(ValueError, match="expected text")` (regex match against the message) or capture `as exc_info` and assert on `str(exc_info.value)`. -
If the code raises
TypeErrorbut the test expectspytest.raises(ValueError), does the test pass?Answer
No โ it fails, because the raised exception type doesn't match (unless `TypeError` were a subclass of `ValueError`, which it isn't).