Raise PT011 only if exception info is unused
Make a new variant of PT011 (pytest-raises-too-broad) that only triggers if the context is unused.
# bad
with pytest.raises(ValueError):
raise ValueError(f"unknown {option=}")
# ok
with pytest.raises(ValueError) as exc:
raise ValueError(f"unknown {option=}")
assert f"unknown {option=}" in str(exc.value)
PT011 currently triggers for both these cases even though the 2nd is plenty specific enough.
Was about to open an issue on this, but it seems this and #6840 already discuss this. I agree with the suggestion.
Just trust us that the excinfo will be checked!
Here is my example (quite similar to #5157):
@pytest.mark.parametrize("mapping", [{}, {"foo": 1, "bar": 1}])
def test_get_val_at_index_not_one_mapping(
self, expression_get_val_at_index, mapping
):
with pytest.raises(ValueError) as excinfo: # noqa: PT011, false positive.
expression_get_val_at_index(**mapping)
assert check_error_or_warning(
excinfo, "Supply one (and only one) dimension:index mapping"
)
imo as long as the exception info variable is used in a following assert statement, it's plenty enough to avoid false-positives whilst minimizing false-negatives.
Using an assert instead of the match param is often desired for exact string matches and to avoid having to escape special regex characters.
This is much more precise
with pytest.raises(ValueError) as excinfo:
function_that_raises()
assert "The complete error" == str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
function_that_raises()
assert "..." in str(excinfo.value)
Than this:
with pytest.raises(ValueError, match="The complete error") as excinfo: # oops, this is a partial match !
function_that_raises()
with pytest.raises(ValueError, match="...") as excinfo: # oops, this matches any 3+ character strings !
function_that_raises()