Skip to content

Commit

Permalink
Fix pytest-raises-too-broad (PT011) to flag pytest.raises call wi…
Browse files Browse the repository at this point in the history
…th keyword `expected_exception` (#14298)

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

`pytest-raises-too-broad (PT011)` should be raised when
`expected_exception` is provided as a keyword argument.

```python
def test_foo():
    with pytest.raises(ValueError):  # raises PT011
        raise ValueError("Can't divide 1 by 0")

    # This is minor but a valid pytest.raises call
    with pytest.raises(expected_exception=ValueError):  # doesn't raise PT011 but should
        raise ValueError("Can't divide 1 by 0")
```

`pytest.raises` doc:
https://docs.pytest.org/en/8.3.x/reference/reference.html#pytest.raises

## Test Plan

<!-- How was it tested? -->

Unit tests

Signed-off-by: harupy <[email protected]>
  • Loading branch information
harupy authored Nov 12, 2024
1 parent 147ea39 commit 2b6d66b
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ def test_error_no_argument_given():
with pytest.raises(ValueError):
raise ValueError("Can't divide 1 by 0")

with pytest.raises(expected_exception=ValueError):
raise ValueError("Can't divide 1 by 0")

with pytest.raises(socket.error):
raise ValueError("Can't divide 1 by 0")

Expand Down
13 changes: 6 additions & 7 deletions crates/ruff_linter/src/rules/flake8_pytest_style/rules/raises.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,12 @@ pub(crate) fn raises_call(checker: &mut Checker, call: &ast::ExprCall) {
}

if checker.enabled(Rule::PytestRaisesTooBroad) {
let match_keyword = call.arguments.find_keyword("match");
if let Some(exception) = call.arguments.args.first() {
if let Some(match_keyword) = match_keyword {
if is_empty_or_null_string(&match_keyword.value) {
exception_needs_match(checker, exception);
}
} else {
if let Some(exception) = call.arguments.find_argument("expected_exception", 0) {
if call
.arguments
.find_keyword("match")
.map_or(true, |k| is_empty_or_null_string(&k.value))
{
exception_needs_match(checker, exception);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@ PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
19 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
19 | raise ValueError("Can't divide 1 by 0")
20 |
21 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
21 | with pytest.raises(expected_exception=ValueError):
| ^^^^^^^^^^ PT011
22 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
31 | def test_error_match_is_empty():
32 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
33 | raise ValueError("Can't divide 1 by 0")
22 | raise ValueError("Can't divide 1 by 0")
23 |
24 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
25 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
33 | raise ValueError("Can't divide 1 by 0")
34 |
35 | with pytest.raises(ValueError, match=""):
34 | def test_error_match_is_empty():
35 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
36 | raise ValueError("Can't divide 1 by 0")
|
Expand All @@ -39,9 +39,16 @@ PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
|
36 | raise ValueError("Can't divide 1 by 0")
37 |
38 | with pytest.raises(ValueError, match=f""):
38 | with pytest.raises(ValueError, match=""):
| ^^^^^^^^^^ PT011
39 | raise ValueError("Can't divide 1 by 0")
|


PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
39 | raise ValueError("Can't divide 1 by 0")
40 |
41 | with pytest.raises(ValueError, match=f""):
| ^^^^^^^^^^ PT011
42 | raise ValueError("Can't divide 1 by 0")
|
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,28 @@ PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
19 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
19 | raise ValueError("Can't divide 1 by 0")
20 |
21 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
21 | with pytest.raises(expected_exception=ValueError):
| ^^^^^^^^^^ PT011
22 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
31 | def test_error_match_is_empty():
32 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
33 | raise ValueError("Can't divide 1 by 0")
22 | raise ValueError("Can't divide 1 by 0")
23 |
24 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
25 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
33 | raise ValueError("Can't divide 1 by 0")
34 |
35 | with pytest.raises(ValueError, match=""):
34 | def test_error_match_is_empty():
35 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
36 | raise ValueError("Can't divide 1 by 0")
|
Expand All @@ -47,9 +47,16 @@ PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
|
36 | raise ValueError("Can't divide 1 by 0")
37 |
38 | with pytest.raises(ValueError, match=f""):
38 | with pytest.raises(ValueError, match=""):
| ^^^^^^^^^^ PT011
39 | raise ValueError("Can't divide 1 by 0")
|


PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
39 | raise ValueError("Can't divide 1 by 0")
40 |
41 | with pytest.raises(ValueError, match=f""):
| ^^^^^^^^^^ PT011
42 | raise ValueError("Can't divide 1 by 0")
|
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,46 @@ PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
19 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:21:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
19 | raise ValueError("Can't divide 1 by 0")
20 |
21 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
21 | with pytest.raises(expected_exception=ValueError):
| ^^^^^^^^^^ PT011
22 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
22 | raise ValueError("Can't divide 1 by 0")
23 |
24 | with pytest.raises(PicklingError):
| ^^^^^^^^^^^^^ PT011
25 | raise PicklingError("Can't pickle")
24 | with pytest.raises(socket.error):
| ^^^^^^^^^^^^ PT011
25 | raise ValueError("Can't divide 1 by 0")
|

PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:27:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
25 | raise PicklingError("Can't pickle")
25 | raise ValueError("Can't divide 1 by 0")
26 |
27 | with pytest.raises(UnpicklingError):
| ^^^^^^^^^^^^^^^ PT011
28 | raise UnpicklingError("Can't unpickle")
27 | with pytest.raises(PicklingError):
| ^^^^^^^^^^^^^ PT011
28 | raise PicklingError("Can't pickle")
|

PT011.py:32:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:30:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
31 | def test_error_match_is_empty():
32 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
33 | raise ValueError("Can't divide 1 by 0")
28 | raise PicklingError("Can't pickle")
29 |
30 | with pytest.raises(UnpicklingError):
| ^^^^^^^^^^^^^^^ PT011
31 | raise UnpicklingError("Can't unpickle")
|

PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
33 | raise ValueError("Can't divide 1 by 0")
34 |
35 | with pytest.raises(ValueError, match=""):
34 | def test_error_match_is_empty():
35 | with pytest.raises(ValueError, match=None):
| ^^^^^^^^^^ PT011
36 | raise ValueError("Can't divide 1 by 0")
|
Expand All @@ -65,9 +65,16 @@ PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match`
|
36 | raise ValueError("Can't divide 1 by 0")
37 |
38 | with pytest.raises(ValueError, match=f""):
38 | with pytest.raises(ValueError, match=""):
| ^^^^^^^^^^ PT011
39 | raise ValueError("Can't divide 1 by 0")
|


PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
39 | raise ValueError("Can't divide 1 by 0")
40 |
41 | with pytest.raises(ValueError, match=f""):
| ^^^^^^^^^^ PT011
42 | raise ValueError("Can't divide 1 by 0")
|
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
---
source: crates/ruff_linter/src/rules/flake8_pytest_style/mod.rs
---
PT011.py:24:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:27:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
22 | raise ValueError("Can't divide 1 by 0")
23 |
24 | with pytest.raises(PicklingError):
25 | raise ValueError("Can't divide 1 by 0")
26 |
27 | with pytest.raises(PicklingError):
| ^^^^^^^^^^^^^ PT011
25 | raise PicklingError("Can't pickle")
28 | raise PicklingError("Can't pickle")
|

PT011.py:27:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
PT011.py:30:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
25 | raise PicklingError("Can't pickle")
26 |
27 | with pytest.raises(UnpicklingError):
28 | raise PicklingError("Can't pickle")
29 |
30 | with pytest.raises(UnpicklingError):
| ^^^^^^^^^^^^^^^ PT011
28 | raise UnpicklingError("Can't unpickle")
31 | raise UnpicklingError("Can't unpickle")
|


0 comments on commit 2b6d66b

Please sign in to comment.