How do I properly assert that an exception gets raised
![]()
There are two ways to handle exceptions in pytest:
- Using pytest.raises to write assertions about raised exceptions
- Using @pytest.mark.xfail
1. Using pytest.raises
From the docs:
In order to write assertions about raised exceptions, you can use pytest.raises as a context manager
Examples:
Asserting just an exception:
import pytest def test_zero_division(): with pytest.raises(ZeroDivisionError): 1 / 0
with pytest.raises(ZeroDivisionError) says that whatever is in the next block of code should raise a ZeroDivisionError exception. If no exception is raised, the test fails. If the test raises a different exception, it fails.
If you need to have access to the actual exception info:
import pytest def f(): f() def test_recursion_depth(): with pytest.raises(RuntimeError) as excinfo: f() assert “maximum recursion” in str(excinfo.value)
excinfo is a ExceptionInfo instance, which is a wrapper around the actual exception raised. The main attributes of interest are .type, .value and .traceback.
2. Using @pytest.mark.xfail
It is also possible to specify a raises argument to pytest.mark.xfail.
import pytest @pytest.mark.xfail(raises=IndexError) def test_f(): l = [1, 2, 3] l[10]
@pytest.mark.xfail(raises=IndexError) says that whatever is in the next block of code should raise an IndexError exception. If an IndexError is raised, test is marked as xfailed (x). If no exception is raised, the test is marked as xpassed (X). If the test raises a different exception, it fails.
Notes:
Using pytest.raises is likely to be better for cases where you are testing exceptions your own code is deliberately raising, whereas using @pytest.mark.xfail with a check function is probably better for something like documenting unfixed bugs or bugs in dependencies.
You can pass a match keyword parameter to the context-manager (pytest.raises) to test that a regular expression matches on the string representation of an exception. (see more)
