Repository: astral-sh/ruff
File: crates/ruff_linter/src/rules/flake8_executable/mod.rs (Rust)

Code before:
        }

        let snapshot = path.to_string_lossy().into_owned();
        let diagnostics = test_path(
            Path::new("flake8_executable").join(path).as_path(),
            &settings::LinterSettings::for_rules(vec![Rule::ShebangMissingPython]),
        )?;
        assert_diagnostics!(snapshot, diagnostics);
        Ok(())
    }

    #[test_case(Path::new("EXE004_1.py"))]
    #[test_case(Path::new("EXE004_2.py"))]
    #[test_case(Path::new("EXE004_3.py"))]
    #[test_case(Path::new("EXE004_4.py"))]
    fn rules_exe004(path: &Path) -> Result<()> {
        if is_wsl::is_wsl() {
            // these rules are always ignored on WSL, so skip testing them in a WSL environment
            // see https://github.com/astral-sh/ruff/pull/21724 for latest discussion
            return Ok(());
        }

        let snapshot = path.to_string_lossy().into_owned();
        let diagnostics = test_path(
            Path::new("flake8_executable").join(path).as_path(),
            &settings::LinterSettings::for_rules(vec![Rule::ShebangLeadingWhitespace]),
        )?;
        assert_diagnostics!(snapshot, diagnostics);
        Ok(())
    }

    #[test_case(Path::new("EXE005_1.py"))]
    #[test_case(Path::new("EXE005_2.py"))]
    #[test_case(Path::new("EXE005_3.py"))]
    fn rules_exe005(path: &Path) -> Result<()> {
        if is_wsl::is_wsl() {
            // these rules are always ignored on WSL, so skip testing them in a WSL environment
            // see https://github.com/astral-sh/ruff/pull/21724 for latest discussion
            return Ok(());
        }

        let snapshot = path.to_string_lossy().into_owned();
        let diagnostics = test_path(
            Path::new("flake8_executable").join(path).as_path(),
            &settings::LinterSettings::for_rules(vec![Rule::ShebangNotFirstLine]),
        )?;
        assert_diagnostics!(snapshot, diagnostics);
        Ok(())
    }
}


Review comment (suggestion):
I think what we usually do here is to pass both the path and the rule as arguments. Would that allow us to combine these test functions again without activating all rules in all tests?


```suggestion
    fn rules(rule: Rule, path: &Path) -> Result<()> {
        if is_wsl::is_wsl() {
            // these rules are always ignored on WSL, so skip testing them in a WSL environment
            // see https://github.com/astral-sh/ruff/pull/21724 for latest discussion
            return Ok(());
        }

        let snapshot = path.to_string_lossy().into_owned();
        let diagnostics = test_path(
            Path::new("flake8_executable").join(path).as_path(),
            &settings::LinterSettings::for_rule(rule),
```

Code after:
//! Rules from [flake8-executable](https://pypi.org/project/flake8-executable/).
pub(crate) mod helpers;
pub(crate) mod rules;

#[cfg(unix)]
#[cfg(test)]
mod tests {
    use std::path::Path;

    use anyhow::Result;
    use test_case::test_case;

    use crate::registry::Rule;
    use crate::test::test_path;
    use crate::{assert_diagnostics, settings};

    #[test_case(Rule::ShebangNotExecutable, Path::new("EXE001_1.py"))]
    #[test_case(Rule::ShebangNotExecutable, Path::new("EXE001_2.py"))]
    #[test_case(Rule::ShebangNotExecutable, Path::new("EXE001_3.py"))]
    #[test_case(Rule::ShebangMissingExecutableFile, Path::new("EXE002_1.py"))]
    #[test_case(Rule::ShebangMissingExecutableFile, Path::new("EXE002_2.py"))]
    #[test_case(Rule::ShebangMissingExecutableFile, Path::new("EXE002_3.py"))]
    #[test_case(Rule::ShebangMissingPython, Path::new("EXE003.py"))]
    #[test_case(Rule::ShebangMissingPython, Path::new("EXE003_uv.py"))]
    #[test_case(Rule::ShebangMissingPython, Path::new("EXE003_uv_tool.py"))]
    #[test_case(Rule::ShebangMissingPython, Path::new("EXE003_uvx.py"))]
    #[test_case(Rule::ShebangLeadingWhitespace, Path::new("EXE004_1.py"))]
    #[test_case(Rule::ShebangLeadingWhitespace, Path::new("EXE004_2.py"))]
    #[test_case(Rule::ShebangLeadingWhitespace, Path::new("EXE004_3.py"))]
    #[test_case(Rule::ShebangLeadingWhitespace, Path::new("EXE004_4.py"))]
    #[test_case(Rule::ShebangNotFirstLine, Path::new("EXE005_1.py"))]
    #[test_case(Rule::ShebangNotFirstLine, Path::new("EXE005_2.py"))]
    #[test_case(Rule::ShebangNotFirstLine, Path::new("EXE005_3.py"))]
    fn rules(rule: Rule, path: &Path) -> Result<()> {
        if is_wsl::is_wsl() {
            // these rules are always ignored on WSL, so skip testing them in a WSL environment
            // see https://github.com/astral-sh/ruff/pull/21724 for latest discussion
            return Ok(());
        }

        let snapshot = path.to_string_lossy().into_owned();
        let diagnostics = test_path(
            Path::new("flake8_executable").join(path).as_path(),
            &settings::LinterSettings::for_rule(rule),
        )?;
        assert_diagnostics!(snapshot, diagnostics);
        Ok(())
    }
}