Testing that an Exception is Raised with pytest.raises

Previously we tested that the validate_url() function returns the given URL if it’s a valid URL. If the given URL is not valid then validate_url() is supposed to raise a ValueError exception. To test this we need to use pytest.raises(). Here is a test that expects validate_url() to raise a ValueError:

def test_validate_url_rejects_urls_without_domains():
    with pytest.raises(ValueError):
        validate_url('http:///path')

This test will fail if the block of code inside the with statement doesn’t raise ValueError, otherwise the test will pass.

It’s often a good idea to use the match argument to pytest.raises to ensure that the exception raised was the one you expected, and not some other exception of the same class. match is a regular expression that has to match against the string representation of the exception or the test will fail:

def test_validate_url_rejects_urls_without_domains():
    with pytest.raises(ValueError, match="^Not a valid URL\: .*"):
        validate_url('http:///path')

Alternatively, if your code raises a specific custom exception class then match may be unnecessary because that type of exception wouldn’t be raised for any other reason.

There’s also pytest.warns(), for testing that code raises a warning in the same way.

Testing that a certain message was logged works differently: use pytest’s builtin caplog fixture.