Search code examples
pythonpytest

How to find a particular exception inside the traceback using pytest


Having a test_raises test like this, which checks that ValueError was raised using pytest.raises:

import pytest


def foo():
    raise RuntimeError("Foo")


def bar():
    try:
        foo()
    except RuntimeError:
        raise ValueError("Bar")


def test_raises():
    with pytest.raises(ValueError, match="Bar"):
        bar()

How can I check within the test that RuntimeError was also raised at some point and that it was raised with the "Foo" message?

It seems like pytest allows you to with pytest.raises(ValueError) as exc_info:, but not sure which is the best way to traverse the ExceptionInfo in order to find the RuntimeError.


Solution

  • You can get it from the getrepr method

    def test_raises():
        with pytest.raises(ValueError, match="Bar") as exc_info:
            bar()
    
        found = False
        for lst in exc_info.getrepr(style="short").chain:
            for tup in lst:
                if hasattr(tup, "reprentries") and "RuntimeErrors" in str(tup.reprentries):
                    found = True
        assert found, "RuntimeError not found in stacktrace"
    

    If you know for sure the location of the error you can remove the loops and hardcode the location, something like

    assert "RuntimeError" in str(exc_info.getrepr(style="short").chain[0][1]), "RuntimeError not found in stacktrace"