SBUK-Tech
SBUK-Tech

Reputation: 1337

Pytest raises does not catch stopiteration error

Pytest does not catch StopIteration errors with pytest.raises.

As an example this fails:

def test_stop_iteration():
    def iterthis():
        for i in range(5):
            yield i
        raise StopIteration("FINISHED")
    model = iterthis()
    next(model)
    next(model)
    next(model)
    next(model)
    next(model)
    with pytest.raises(StopIteration):
        next(model)

But this passes:


def test_stop_iteration():
    def iterthis():
        for i in range(5):
            yield i
        raise StopIteration("FINISHED")
    model = iterthis()
    next(model)
    next(model)
    next(model)
    next(model)
    next(model)
    with pytest.raises(Exception):
        next(model)

Am I missing something here?

Upvotes: 1

Views: 954

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16815

This is covered in the documentation:

If a generator code directly or indirectly raises StopIteration, it is converted into a RuntimeError (retaining the StopIteration as the new exception’s cause).

So, if you really need to catch it this way, you have to catch RuntimeError instead:

    with pytest.raises(RuntimeError) as e:
        next(model)
    assert "StopIteration" in str(e.value)

The exception also contains the message "generator raised StopIteration" as the cause, so you can check for that. Note that this behavior is specific to generators. If you would just raise a StopIteration outside of a generator it would behave like any other exception:

def test_stop_iteration():
    def raise_stopiter():
        raise StopIteration("FINISHED")

    with pytest.raises(StopIteration):
        raise_stopiter()

Upvotes: 4

Related Questions