mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 11:59:35 +00:00
Support 'reason' argument to pytest.fail
(#5040)
## Summary Per the [API reference](https://docs.pytest.org/en/7.1.x/reference/reference.html#pytest.fail), `reason` was added in version 7, and is equivalent to `msg` (but preferred going forward). I also grepped for `msg` usages in `flake8_pytest_style`, but found no others (apart from those that reference `unittest` APIs.) Closes #3387.
This commit is contained in:
parent
e2130707f5
commit
cbd4c10fdd
4 changed files with 75 additions and 43 deletions
|
@ -1,17 +1,25 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_xxx():
|
# OK
|
||||||
pytest.fail("this is a failure") # Test OK arg
|
def f():
|
||||||
|
pytest.fail("this is a failure")
|
||||||
|
|
||||||
|
|
||||||
def test_xxx():
|
def f():
|
||||||
pytest.fail(msg="this is a failure") # Test OK kwarg
|
pytest.fail(msg="this is a failure")
|
||||||
|
|
||||||
|
|
||||||
def test_xxx(): # Error
|
def f():
|
||||||
|
pytest.fail(reason="this is a failure")
|
||||||
|
|
||||||
|
|
||||||
|
# Errors
|
||||||
|
def f():
|
||||||
pytest.fail()
|
pytest.fail()
|
||||||
pytest.fail("")
|
pytest.fail("")
|
||||||
pytest.fail(f"")
|
pytest.fail(f"")
|
||||||
pytest.fail(msg="")
|
pytest.fail(msg="")
|
||||||
pytest.fail(msg=f"")
|
pytest.fail(msg=f"")
|
||||||
|
pytest.fail(reason="")
|
||||||
|
pytest.fail(reason=f"")
|
||||||
|
|
|
@ -21,7 +21,12 @@ impl Violation for PytestFailWithoutMessage {
|
||||||
pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) {
|
pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) {
|
||||||
if is_pytest_fail(checker.semantic_model(), func) {
|
if is_pytest_fail(checker.semantic_model(), func) {
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
let msg = call_args.argument("msg", 0);
|
|
||||||
|
// Allow either `pytest.fail(reason="...")` (introduced in pytest 7.0) or
|
||||||
|
// `pytest.fail(msg="...")` (deprecated in pytest 7.0)
|
||||||
|
let msg = call_args
|
||||||
|
.argument("reason", 0)
|
||||||
|
.or_else(|| call_args.argument("msg", 0));
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
if is_empty_or_null_string(msg) {
|
if is_empty_or_null_string(msg) {
|
||||||
|
|
|
@ -206,9 +206,7 @@ impl UnittestAssert {
|
||||||
keywords: &'a [Keyword],
|
keywords: &'a [Keyword],
|
||||||
) -> Result<FxHashMap<&'a str, &'a Expr>> {
|
) -> Result<FxHashMap<&'a str, &'a Expr>> {
|
||||||
// If we have variable-length arguments, abort.
|
// If we have variable-length arguments, abort.
|
||||||
if args.iter().any(|arg| matches!(arg, Expr::Starred(_)))
|
if args.iter().any(Expr::is_starred_expr) || keywords.iter().any(|kw| kw.arg.is_none()) {
|
||||||
|| keywords.iter().any(|kw| kw.arg.is_none())
|
|
||||||
{
|
|
||||||
bail!("Variable-length arguments are not supported");
|
bail!("Variable-length arguments are not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,14 +261,14 @@ impl UnittestAssert {
|
||||||
.ok_or_else(|| anyhow!("Missing argument `expr`"))?;
|
.ok_or_else(|| anyhow!("Missing argument `expr`"))?;
|
||||||
let msg = args.get("msg").copied();
|
let msg = args.get("msg").copied();
|
||||||
Ok(if matches!(self, UnittestAssert::False) {
|
Ok(if matches!(self, UnittestAssert::False) {
|
||||||
let node = expr.clone();
|
assert(
|
||||||
let node1 = Expr::UnaryOp(ast::ExprUnaryOp {
|
&Expr::UnaryOp(ast::ExprUnaryOp {
|
||||||
op: Unaryop::Not,
|
op: Unaryop::Not,
|
||||||
operand: Box::new(node),
|
operand: Box::new(expr.clone()),
|
||||||
range: TextRange::default(),
|
range: TextRange::default(),
|
||||||
});
|
}),
|
||||||
let unary_expr = node1;
|
msg,
|
||||||
assert(&unary_expr, msg)
|
)
|
||||||
} else {
|
} else {
|
||||||
assert(expr, msg)
|
assert(expr, msg)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,49 +1,70 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff/src/rules/flake8_pytest_style/mod.rs
|
source: crates/ruff/src/rules/flake8_pytest_style/mod.rs
|
||||||
---
|
---
|
||||||
PT016.py:13:5: PT016 No message passed to `pytest.fail()`
|
PT016.py:19:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
|
||||||
12 | def test_xxx(): # Error
|
17 | # Errors
|
||||||
13 | pytest.fail()
|
18 | def f():
|
||||||
|
19 | pytest.fail()
|
||||||
| ^^^^^^^^^^^ PT016
|
| ^^^^^^^^^^^ PT016
|
||||||
14 | pytest.fail("")
|
20 | pytest.fail("")
|
||||||
15 | pytest.fail(f"")
|
21 | pytest.fail(f"")
|
||||||
|
|
|
|
||||||
|
|
||||||
PT016.py:14:5: PT016 No message passed to `pytest.fail()`
|
PT016.py:20:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
|
||||||
12 | def test_xxx(): # Error
|
18 | def f():
|
||||||
13 | pytest.fail()
|
19 | pytest.fail()
|
||||||
14 | pytest.fail("")
|
20 | pytest.fail("")
|
||||||
| ^^^^^^^^^^^ PT016
|
| ^^^^^^^^^^^ PT016
|
||||||
15 | pytest.fail(f"")
|
21 | pytest.fail(f"")
|
||||||
16 | pytest.fail(msg="")
|
22 | pytest.fail(msg="")
|
||||||
|
|
|
|
||||||
|
|
||||||
PT016.py:15:5: PT016 No message passed to `pytest.fail()`
|
PT016.py:21:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
|
||||||
13 | pytest.fail()
|
19 | pytest.fail()
|
||||||
14 | pytest.fail("")
|
20 | pytest.fail("")
|
||||||
15 | pytest.fail(f"")
|
21 | pytest.fail(f"")
|
||||||
| ^^^^^^^^^^^ PT016
|
| ^^^^^^^^^^^ PT016
|
||||||
16 | pytest.fail(msg="")
|
22 | pytest.fail(msg="")
|
||||||
17 | pytest.fail(msg=f"")
|
23 | pytest.fail(msg=f"")
|
||||||
|
|
|
|
||||||
|
|
||||||
PT016.py:16:5: PT016 No message passed to `pytest.fail()`
|
PT016.py:22:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
|
||||||
14 | pytest.fail("")
|
20 | pytest.fail("")
|
||||||
15 | pytest.fail(f"")
|
21 | pytest.fail(f"")
|
||||||
16 | pytest.fail(msg="")
|
22 | pytest.fail(msg="")
|
||||||
| ^^^^^^^^^^^ PT016
|
| ^^^^^^^^^^^ PT016
|
||||||
17 | pytest.fail(msg=f"")
|
23 | pytest.fail(msg=f"")
|
||||||
|
24 | pytest.fail(reason="")
|
||||||
|
|
|
|
||||||
|
|
||||||
PT016.py:17:5: PT016 No message passed to `pytest.fail()`
|
PT016.py:23:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
|
||||||
15 | pytest.fail(f"")
|
21 | pytest.fail(f"")
|
||||||
16 | pytest.fail(msg="")
|
22 | pytest.fail(msg="")
|
||||||
17 | pytest.fail(msg=f"")
|
23 | pytest.fail(msg=f"")
|
||||||
|
| ^^^^^^^^^^^ PT016
|
||||||
|
24 | pytest.fail(reason="")
|
||||||
|
25 | pytest.fail(reason=f"")
|
||||||
|
|
|
||||||
|
|
||||||
|
PT016.py:24:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
||||||
|
22 | pytest.fail(msg="")
|
||||||
|
23 | pytest.fail(msg=f"")
|
||||||
|
24 | pytest.fail(reason="")
|
||||||
|
| ^^^^^^^^^^^ PT016
|
||||||
|
25 | pytest.fail(reason=f"")
|
||||||
|
|
|
||||||
|
|
||||||
|
PT016.py:25:5: PT016 No message passed to `pytest.fail()`
|
||||||
|
|
|
||||||
|
23 | pytest.fail(msg=f"")
|
||||||
|
24 | pytest.fail(reason="")
|
||||||
|
25 | pytest.fail(reason=f"")
|
||||||
| ^^^^^^^^^^^ PT016
|
| ^^^^^^^^^^^ PT016
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue