Fix pytest-raises-too-broad (PT011) to flag pytest.raises call with 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 <hkawamura0130@gmail.com>
This commit is contained in:
Harutaka Kawamura
2024-11-13 04:28:42 +09:00
committed by GitHub
parent 147ea399fd
commit 2b6d66b793
6 changed files with 91 additions and 70 deletions

View File

@@ -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")

View File

@@ -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);
}
}

View File

@@ -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")
|
@@ -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")
|

View File

@@ -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")
|
@@ -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")
|

View File

@@ -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")
|
@@ -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")
|

View File

@@ -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):
| ^^^^^^^^^^^^^ PT011
25 | 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
|
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:30:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
28 | raise PicklingError("Can't pickle")
29 |
30 | with pytest.raises(UnpicklingError):
| ^^^^^^^^^^^^^^^ PT011
31 | raise UnpicklingError("Can't unpickle")
|