ben5756
ben5756

Reputation: 374

How do you test for an exception in python 3 with pytest when the exceptions are chained

I have some code that uses custom exceptions in python 3.

something like:

def get_my_custom_error():
    try:
        1.0/0.0
    except ZeroDivisionError as err:
        raise MyCustomError() from err

and in my test file I have the following:

with pytest.raises(MyCustomError):
    get_my_custom_error()

I currently get an output like

ZeroDivisionError
    
the above exception was the direct cause of the following error:

MyCustomError

This causes the test to fail.

So the code appears to be working, but pytest doesn't seem to be checking the highest level error (which is what I would like it to do).

Python 3.6.1 :: Anaconda 4.4.0 pytest 3.0.7

Any help would be amazing.

Upvotes: 7

Views: 1069

Answers (3)

Tiansu Yu
Tiansu Yu

Reputation: 13

This works at least on python=3.10, pytest=7.4:

with pytest.raises(ZeroDevisionError):
    with pytest.raises(MyCustomError):
        get_my_custom_error()

Notice that the order matters. It must follow the order how the exception is raised.

Upvotes: 0

Jasha
Jasha

Reputation: 7639

Building off phd's answer, you can use pytest.raises to catch the top-level MyCustomError exception, then inspect the object returned by pytest.raises.__enter__ to verify that the chained exception is an instance of ZeroDivisionError.

with pytest.raises(MyCustomError) as exc_info:
    get_my_custom_error()

err = exc_info.value
assert hasattr(err, '__cause__')
assert isinstance(err.__cause__, ZeroDivisionError)

Upvotes: 0

phd
phd

Reputation: 94453

Catch and check it explicitly:

try:
    get_my_custom_error()
except ZeroDivisionError as err:
    assert hasattr(err, '__cause__') and isinstance(err.__cause__, MyCustomError)

Upvotes: 2

Related Questions