forked from astral-sh/ruff
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[
flake8-pytest-style
] Test function parameters with default argumen…
…ts (`PT028`) (astral-sh#15449)
- Loading branch information
1 parent
56b1445
commit 47d0a8b
Showing
11 changed files
with
484 additions
and
4 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/PT028.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Errors | ||
|
||
def test_foo(a=1): ... | ||
def test_foo(a = 1): ... | ||
def test_foo(a = (1)): ... | ||
def test_foo(a: int=1): ... | ||
def test_foo(a: int = 1): ... | ||
def test_foo(a: (int) = 1): ... | ||
def test_foo(a: int = (1)): ... | ||
def test_foo(a: (int) = (1)): ... | ||
def test_foo(a=1, /, b=2, *, c=3): ... | ||
|
||
|
||
# No errors | ||
|
||
def test_foo(a): ... | ||
def test_foo(a: int): ... |
17 changes: 17 additions & 0 deletions
17
crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/is_pytest_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Errors | ||
|
||
def test_this_is_a_test(a=1): ... | ||
def testThisIsAlsoATest(a=1): ... | ||
|
||
class TestClass: | ||
def test_this_too_is_a_test(self, a=1): ... | ||
def testAndOfCourseThis(self, a=1): ... | ||
|
||
|
||
# No errors | ||
|
||
def this_is_not_a_test(a=1): ... | ||
|
||
class TestClassLookalike: | ||
def __init__(self): ... | ||
def test_this_is_not_a_test(self, a=1): ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
crates/ruff_linter/src/rules/flake8_pytest_style/rules/test_functions.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use crate::checkers::ast::Checker; | ||
use crate::rules::flake8_pytest_style::rules::helpers::is_likely_pytest_test; | ||
use ruff_diagnostics::{Diagnostic, Edit, Fix, Violation}; | ||
use ruff_macros::{derive_message_formats, ViolationMetadata}; | ||
use ruff_python_ast::{ParameterWithDefault, StmtFunctionDef}; | ||
use ruff_text_size::Ranged; | ||
|
||
/// ## What it does | ||
/// Checks for parameters of test functions with default arguments. | ||
/// | ||
/// ## Why is this bad? | ||
/// Such a parameter will always have the default value during the test | ||
/// regardless of whether a fixture with the same name is defined. | ||
/// | ||
/// ## Example | ||
/// | ||
/// ```python | ||
/// def test_foo(a=1): ... | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// | ||
/// ```python | ||
/// def test_foo(a): ... | ||
/// ``` | ||
/// | ||
/// ## Fix safety | ||
/// This rule's fix is marked as unsafe, as modifying a function signature can | ||
/// change the behavior of the code. | ||
/// | ||
/// ## References | ||
/// - [Original Pytest issue](https://github.com/pytest-dev/pytest/issues/12693) | ||
#[derive(ViolationMetadata)] | ||
pub(crate) struct PytestParameterWithDefaultArgument { | ||
parameter_name: String, | ||
} | ||
|
||
impl Violation for PytestParameterWithDefaultArgument { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!( | ||
"Test function parameter `{}` has default argument", | ||
self.parameter_name | ||
) | ||
} | ||
|
||
fn fix_title(&self) -> Option<String> { | ||
Some("Remove default argument".to_string()) | ||
} | ||
} | ||
|
||
/// PT028 | ||
pub(crate) fn parameter_with_default_argument( | ||
checker: &mut Checker, | ||
function_def: &StmtFunctionDef, | ||
) { | ||
if !is_likely_pytest_test(function_def, checker) { | ||
return; | ||
} | ||
|
||
let parameters = function_def.parameters.as_ref(); | ||
|
||
for ParameterWithDefault { | ||
parameter, | ||
default, | ||
range: pwd_range, | ||
} in parameters.iter_non_variadic_params() | ||
{ | ||
let Some(default) = default else { | ||
continue; | ||
}; | ||
|
||
let parameter_name = parameter.name.to_string(); | ||
let kind = PytestParameterWithDefaultArgument { parameter_name }; | ||
let diagnostic = Diagnostic::new(kind, default.range()); | ||
|
||
let edit = Edit::deletion(parameter.end(), pwd_range.end()); | ||
let fix = Fix::display_only_edit(edit); | ||
|
||
checker.diagnostics.push(diagnostic.with_fix(fix)); | ||
} | ||
} |
Oops, something went wrong.