From 0b8de723c6cfca90f1a1a1e4512b78c549652eb5 Mon Sep 17 00:00:00 2001 From: Renkai Ge Date: Sun, 19 Oct 2025 18:25:21 +0800 Subject: [PATCH] Refactor format tests to use CliTest helper (#20953) Co-authored-by: Micha Reiser --- crates/ruff/tests/{ => cli}/format.rs | 1244 ++++++++--------- crates/ruff/tests/cli/main.rs | 17 + .../cli__format__output_format_azure.snap} | 2 +- .../cli__format__output_format_concise.snap} | 2 +- .../cli__format__output_format_full.snap} | 2 +- .../cli__format__output_format_github.snap} | 2 +- .../cli__format__output_format_gitlab.snap} | 2 +- .../cli__format__output_format_grouped.snap} | 3 +- ...li__format__output_format_json-lines.snap} | 2 +- .../cli__format__output_format_json.snap} | 2 +- .../cli__format__output_format_junit.snap} | 2 +- .../cli__format__output_format_pylint.snap} | 3 +- .../cli__format__output_format_rdjson.snap} | 2 +- .../cli__format__output_format_sarif.snap} | 2 +- 14 files changed, 606 insertions(+), 681 deletions(-) rename crates/ruff/tests/{ => cli}/format.rs (65%) rename crates/ruff/tests/{snapshots/format__output_format_azure.snap => cli/snapshots/cli__format__output_format_azure.snap} (89%) rename crates/ruff/tests/{snapshots/format__output_format_concise.snap => cli/snapshots/cli__format__output_format_concise.snap} (88%) rename crates/ruff/tests/{snapshots/format__output_format_full.snap => cli/snapshots/cli__format__output_format_full.snap} (90%) rename crates/ruff/tests/{snapshots/format__output_format_github.snap => cli/snapshots/cli__format__output_format_github.snap} (90%) rename crates/ruff/tests/{snapshots/format__output_format_gitlab.snap => cli/snapshots/cli__format__output_format_gitlab.snap} (93%) rename crates/ruff/tests/{snapshots/format__output_format_grouped.snap => cli/snapshots/cli__format__output_format_grouped.snap} (83%) rename crates/ruff/tests/{snapshots/format__output_format_json-lines.snap => cli/snapshots/cli__format__output_format_json-lines.snap} (93%) rename crates/ruff/tests/{snapshots/format__output_format_json.snap => cli/snapshots/cli__format__output_format_json.snap} (95%) rename crates/ruff/tests/{snapshots/format__output_format_junit.snap => cli/snapshots/cli__format__output_format_junit.snap} (94%) rename crates/ruff/tests/{snapshots/format__output_format_pylint.snap => cli/snapshots/cli__format__output_format_pylint.snap} (81%) rename crates/ruff/tests/{snapshots/format__output_format_rdjson.snap => cli/snapshots/cli__format__output_format_rdjson.snap} (96%) rename crates/ruff/tests/{snapshots/format__output_format_sarif.snap => cli/snapshots/cli__format__output_format_sarif.snap} (97%) diff --git a/crates/ruff/tests/format.rs b/crates/ruff/tests/cli/format.rs similarity index 65% rename from crates/ruff/tests/format.rs rename to crates/ruff/tests/cli/format.rs index 6205fa98e8..7ab9e59f26 100644 --- a/crates/ruff/tests/format.rs +++ b/crates/ruff/tests/cli/format.rs @@ -2,24 +2,17 @@ use std::fs; use std::path::Path; -use std::process::Command; -use std::str; use anyhow::Result; -use insta_cmd::{assert_cmd_snapshot, get_cargo_bin}; -use regex::escape; -use tempfile::TempDir; +use insta_cmd::assert_cmd_snapshot; -const BIN_NAME: &str = "ruff"; - -fn tempdir_filter(path: impl AsRef) -> String { - format!(r"{}\\?/?", escape(path.as_ref().to_str().unwrap())) -} +use super::{CliTest, tempdir_filter}; #[test] -fn default_options() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py"]) +fn default_options() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -46,26 +39,19 @@ if condition: ----- stderr ----- "#); + Ok(()) } #[test] fn default_files() -> Result<()> { - let tempdir = TempDir::new()?; - fs::write( - tempdir.path().join("foo.py"), - r#" -foo = "needs formatting" -"#, - )?; - fs::write( - tempdir.path().join("bar.py"), - r#" -bar = "needs formatting" -"#, - )?; + let test = CliTest::with_files([ + ("foo.py", r#"foo = "needs formatting""#), + ("bar.py", r#"bar = "needs formatting""#), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--no-cache", "--check"]).current_dir(tempdir.path()), @r" + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--check"), @r" success: false exit_code: 1 ----- stdout ----- @@ -80,9 +66,10 @@ bar = "needs formatting" } #[test] -fn format_warn_stdin_filename_with_files() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "foo.py"]) +fn format_warn_stdin_filename_with_files() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "foo.py"]) .arg("foo.py") .pass_stdin("foo = 1"), @r" success: true @@ -93,12 +80,14 @@ fn format_warn_stdin_filename_with_files() { ----- stderr ----- warning: Ignoring file foo.py in favor of standard input. "); + Ok(()) } #[test] -fn nonexistent_config_file() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config", "foo.toml", "."]), @r" +fn nonexistent_config_file() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--config", "foo.toml", "."]), @r" success: false exit_code: 2 ----- stdout ----- @@ -115,12 +104,14 @@ fn nonexistent_config_file() { For more information, try '--help'. "); + Ok(()) } #[test] -fn config_override_rejected_if_invalid_toml() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config", "foo = bar", "."]), @r" +fn config_override_rejected_if_invalid_toml() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--config", "foo = bar", "."]), @r" success: false exit_code: 2 ----- stdout ----- @@ -142,84 +133,69 @@ fn config_override_rejected_if_invalid_toml() { For more information, try '--help'. "); + Ok(()) } #[test] fn too_many_config_files() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_dot_toml = tempdir.path().join("ruff.toml"); - let ruff2_dot_toml = tempdir.path().join("ruff2.toml"); - fs::File::create(&ruff_dot_toml)?; - fs::File::create(&ruff2_dot_toml)?; - insta::with_settings!({ - filters => vec![(tempdir_filter(&tempdir).as_str(), "[TMP]/")] - }, { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .arg("format") + let test = CliTest::with_files([("ruff.toml", ""), ("ruff2.toml", "")])?; + + assert_cmd_snapshot!(test.format_command() .arg("--config") - .arg(&ruff_dot_toml) + .arg("ruff.toml") .arg("--config") - .arg(&ruff2_dot_toml) + .arg("ruff2.toml") .arg("."), @r" - success: false - exit_code: 2 - ----- stdout ----- + success: false + exit_code: 2 + ----- stdout ----- - ----- stderr ----- - ruff failed - Cause: You cannot specify more than one configuration file on the command line. + ----- stderr ----- + ruff failed + Cause: You cannot specify more than one configuration file on the command line. - tip: remove either `--config=[TMP]/ruff.toml` or `--config=[TMP]/ruff2.toml`. - For more information, try `--help`. - "); - }); + tip: remove either `--config=ruff.toml` or `--config=ruff2.toml`. + For more information, try `--help`. + "); Ok(()) } #[test] fn config_file_and_isolated() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_dot_toml = tempdir.path().join("ruff.toml"); - fs::File::create(&ruff_dot_toml)?; - insta::with_settings!({ - filters => vec![(tempdir_filter(&tempdir).as_str(), "[TMP]/")] - }, { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .arg("format") - .arg("--config") - .arg(&ruff_dot_toml) + let test = CliTest::with_file("ruff.toml", "")?; + + assert_cmd_snapshot!(test.format_command() .arg("--isolated") + .arg("--config") + .arg("ruff.toml") .arg("."), @r" - success: false - exit_code: 2 - ----- stdout ----- + success: false + exit_code: 2 + ----- stdout ----- - ----- stderr ----- - ruff failed - Cause: The argument `--config=[TMP]/ruff.toml` cannot be used with `--isolated` + ----- stderr ----- + ruff failed + Cause: The argument `--config=ruff.toml` cannot be used with `--isolated` - tip: You cannot specify a configuration file and also specify `--isolated`, - as `--isolated` causes ruff to ignore all configuration files. - For more information, try `--help`. - "); - }); + tip: You cannot specify a configuration file and also specify `--isolated`, + as `--isolated` causes ruff to ignore all configuration files. + For more information, try `--help`. + "); Ok(()) } #[test] fn config_override_via_cli() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write(&ruff_toml, "line-length = 100")?; + let test = CliTest::with_file("ruff.toml", "line-length = 70")?; + let fixture = r#" def foo(): print("looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string") "#; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .arg("format") + assert_cmd_snapshot!(test.format_command() .arg("--config") - .arg(&ruff_toml) + .arg("ruff.toml") // This overrides the long line length set in the config file .args(["--config", "line-length=80"]) .arg("-") @@ -239,18 +215,16 @@ def foo(): #[test] fn config_doubly_overridden_via_cli() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write(&ruff_toml, "line-length = 70")?; + let test = CliTest::with_file("ruff.toml", "line-length = 70")?; + let fixture = r#" def foo(): print("looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string") "#; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .arg("format") + assert_cmd_snapshot!(test.format_command() .arg("--config") - .arg(&ruff_toml) + .arg("ruff.toml") // This overrides the long line length set in the config file... .args(["--config", "line-length=80"]) // ...but this overrides them both: @@ -270,10 +244,8 @@ def foo(): #[test] fn format_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r#" indent-width = 8 line-length = 84 @@ -286,9 +258,9 @@ line-ending = "cr-lf" "#, )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config"]) - .arg(&ruff_toml) + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -319,10 +291,8 @@ if condition: #[test] fn docstring_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r" [format] docstring-code-format = true @@ -330,9 +300,9 @@ docstring-code-line-length = 20 ", )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config"]) - .arg(&ruff_toml) + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") .arg("-") .pass_stdin(r" def f(x): @@ -406,21 +376,20 @@ def f(x): #[test] fn mixed_line_endings() -> Result<()> { - let tempdir = TempDir::new()?; + let test = CliTest::with_files([ + ( + "main.py", + "from test import say_hy\n\nif __name__ == \"__main__\":\n say_hy(\"dear Ruff contributor\")\n", + ), + ( + "test.py", + "def say_hy(name: str):\r\n print(f\"Hy {name}\")\r\n", + ), + ])?; - fs::write( - tempdir.path().join("main.py"), - "from test import say_hy\n\nif __name__ == \"__main__\":\n say_hy(\"dear Ruff contributor\")\n", - )?; - - fs::write( - tempdir.path().join("test.py"), - "def say_hy(name: str):\r\n print(f\"Hy {name}\")\r\n", - )?; - - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--diff", "--isolated"]) + assert_cmd_snapshot!(test.format_command() + .arg("--diff") + .arg("--isolated") .arg("."), @r" success: true exit_code: 0 @@ -434,58 +403,48 @@ fn mixed_line_endings() -> Result<()> { #[test] fn exclude() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" extend-exclude = ["out"] [format] exclude = ["test.py", "generated.py"] "#, - )?; - - fs::write( - tempdir.path().join("main.py"), - r#" + ), + ( + "main.py", + r#" from test import say_hy if __name__ == "__main__": say_hy("dear Ruff contributor") "#, - )?; - - // Excluded file but passed to the CLI directly, should be formatted - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + // Excluded file but passed to the CLI directly, should be formatted + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; - - fs::write( - tempdir.path().join("generated.py"), - r#"NUMBERS = [ + ), + ( + "generated.py", + r#"NUMBERS = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ] OTHER = "OTHER" "#, - )?; + ), + ("out/a.py", "a = a"), + ])?; - let out_dir = tempdir.path().join("out"); - fs::create_dir(&out_dir)?; - - fs::write(out_dir.join("a.py"), "a = a")?; - - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--check", "--config"]) - .arg(ruff_toml.file_name().unwrap()) + assert_cmd_snapshot!(test.format_command() + .args(["--check", "--config", "ruff.toml"]) // Explicitly pass test.py, should be formatted regardless of it being excluded by format.exclude - .arg(test_path.file_name().unwrap()) + .arg("test.py") // Format all other files in the directory, should respect the `exclude` and `format.exclude` options .arg("."), @r" success: false @@ -503,16 +462,11 @@ OTHER = "OTHER" /// Regression test for #[test] fn deduplicate_directory_and_explicit_file() -> Result<()> { - let tempdir = TempDir::new()?; - let root = tempdir.path(); - - let main = root.join("main.py"); - fs::write(&main, "x = 1\n")?; + let test = CliTest::with_file("main.py", "x = 1\n")?; assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(root) - .args(["format", "--no-cache", "--check"]) + test.format_command() + .arg("--check") .arg(".") .arg("main.py"), @r" @@ -531,18 +485,16 @@ fn deduplicate_directory_and_explicit_file() -> Result<()> { #[test] fn syntax_error() -> Result<()> { - let tempdir = TempDir::new()?; - - fs::write( - tempdir.path().join("main.py"), + let test = CliTest::with_file( + "main.py", r" from module import = ", )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--isolated", "--check"]) + assert_cmd_snapshot!(test.format_command() + .arg("--check") + .arg("--isolated") .arg("main.py"), @r" success: false exit_code: 2 @@ -557,10 +509,8 @@ from module import = #[test] fn messages() -> Result<()> { - let tempdir = TempDir::new()?; - - fs::write( - tempdir.path().join("main.py"), + let test = CliTest::with_file( + "main.py", r#" from test import say_hy @@ -569,9 +519,9 @@ if __name__ == "__main__": "#, )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--isolated", "--check"]) + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--check") .arg("main.py"), @r" success: false exit_code: 1 @@ -582,9 +532,8 @@ if __name__ == "__main__": ----- stderr ----- "); - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--isolated"]) + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") .arg("main.py"), @r" success: true exit_code: 0 @@ -594,9 +543,8 @@ if __name__ == "__main__": ----- stderr ----- "); - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--isolated"]) + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") .arg("main.py"), @r" success: true exit_code: 0 @@ -629,95 +577,87 @@ if __name__ == "__main__": say_hy("dear Ruff contributor") "#; - let tempdir = TempDir::new()?; - let input = tempdir.path().join("input.py"); - fs::write(&input, CONTENT)?; + let test = CliTest::with_settings(|_project_dir, mut settings| { + // JSON double escapes backslashes + settings.add_filter(r#""[^"]+\\?/?input.py"#, r#""[TMP]/input.py"#); + + settings + })?; + test.write_file("input.py", CONTENT)?; let snapshot = format!("output_format_{output_format}"); - let project_dir = dunce::canonicalize(tempdir.path())?; - - insta::with_settings!({ - filters => vec![ - (tempdir_filter(&project_dir).as_str(), "[TMP]/"), - (tempdir_filter(&tempdir).as_str(), "[TMP]/"), - (r#""[^"]+\\?/?input.py"#, r#""[TMP]/input.py"#), - (ruff_linter::VERSION, "[VERSION]"), - ] - }, { - assert_cmd_snapshot!( - snapshot, - Command::new(get_cargo_bin(BIN_NAME)) - .args([ - "format", - "--no-cache", - "--output-format", - output_format, - "--preview", - "--check", - "input.py", - ]) - .current_dir(&tempdir), - ); - }); + assert_cmd_snapshot!( + snapshot, + test.format_command().args([ + "--output-format", + output_format, + "--preview", + "--check", + "input.py", + ]), + ); Ok(()) } #[test] -fn output_format_notebook() { - let args = ["format", "--no-cache", "--isolated", "--preview", "--check"]; - let fixtures = Path::new("resources").join("test").join("fixtures"); +fn output_format_notebook() -> Result<()> { + let crate_root = Path::new(env!("CARGO_MANIFEST_DIR")); + let fixtures = crate_root.join("resources").join("test").join("fixtures"); let path = fixtures.join("unformatted.ipynb"); - insta::with_settings!({filters => vec![ - // Replace windows paths - (r"\\", "/"), - ]}, { - assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)).args(args).arg(path), - @r" - success: false - exit_code: 1 - ----- stdout ----- - unformatted: File would be reformatted - --> resources/test/fixtures/unformatted.ipynb:cell 1:1:1 - ::: cell 1 - 1 | import numpy - - maths = (numpy.arange(100)**2).sum() - - stats= numpy.asarray([1,2,3,4]).median() - 2 + - 3 + maths = (numpy.arange(100) ** 2).sum() - 4 + stats = numpy.asarray([1, 2, 3, 4]).median() - ::: cell 3 - 1 | # A cell with IPython escape command - 2 | def some_function(foo, bar): - 3 | pass - 4 + - 5 + - 6 | %matplotlib inline - ::: cell 4 - 1 | foo = %pwd - - def some_function(foo,bar,): - 2 + - 3 + - 4 + def some_function( - 5 + foo, - 6 + bar, - 7 + ): - 8 | # Another cell with IPython escape command - 9 | foo = %pwd - 10 | print(foo) - 1 file would be reformatted + let test = CliTest::with_settings(|_, mut settings| { + settings.add_filter(&tempdir_filter(crate_root.to_str().unwrap()), "CRATE_ROOT/"); + settings + })?; - ----- stderr ----- - "); - }); + assert_cmd_snapshot!( + test.format_command().args(["--isolated", "--preview", "--check"]).arg(path), + @r" + success: false + exit_code: 1 + ----- stdout ----- + unformatted: File would be reformatted + --> CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 1:1:1 + ::: cell 1 + 1 | import numpy + - maths = (numpy.arange(100)**2).sum() + - stats= numpy.asarray([1,2,3,4]).median() + 2 + + 3 + maths = (numpy.arange(100) ** 2).sum() + 4 + stats = numpy.asarray([1, 2, 3, 4]).median() + ::: cell 3 + 1 | # A cell with IPython escape command + 2 | def some_function(foo, bar): + 3 | pass + 4 + + 5 + + 6 | %matplotlib inline + ::: cell 4 + 1 | foo = %pwd + - def some_function(foo,bar,): + 2 + + 3 + + 4 + def some_function( + 5 + foo, + 6 + bar, + 7 + ): + 8 | # Another cell with IPython escape command + 9 | foo = %pwd + 10 | print(foo) + + 1 file would be reformatted + + ----- stderr ----- + " + ); + Ok(()) } #[test] fn exit_non_zero_on_format() -> Result<()> { - let tempdir = TempDir::new()?; + let test = CliTest::new()?; let contents = r#" from test import say_hy @@ -726,20 +666,13 @@ if __name__ == "__main__": say_hy("dear Ruff contributor") "#; - fs::write(tempdir.path().join("main.py"), contents)?; - - let mut cmd = Command::new(get_cargo_bin(BIN_NAME)); - cmd.current_dir(tempdir.path()) - .args([ - "format", - "--no-cache", - "--isolated", - "--exit-non-zero-on-format", - ]) - .arg("main.py"); + test.write_file("main.py", contents)?; // First format should exit with code 1 since the file needed formatting - assert_cmd_snapshot!(cmd, @r" + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--exit-non-zero-on-format") + .arg("main.py"), @r" success: false exit_code: 1 ----- stdout ----- @@ -749,7 +682,10 @@ if __name__ == "__main__": "); // Second format should exit with code 0 since no files needed formatting - assert_cmd_snapshot!(cmd, @r" + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--exit-non-zero-on-format") + .arg("main.py"), @r" success: true exit_code: 0 ----- stdout ----- @@ -759,20 +695,13 @@ if __name__ == "__main__": "); // Repeat the tests above with the --exit-non-zero-on-fix alias - fs::write(tempdir.path().join("main.py"), contents)?; - - let mut cmd = Command::new(get_cargo_bin(BIN_NAME)); - cmd.current_dir(tempdir.path()) - .args([ - "format", - "--no-cache", - "--isolated", - "--exit-non-zero-on-fix", - ]) - .arg("main.py"); + test.write_file("main.py", contents)?; // First format should exit with code 1 since the file needed formatting - assert_cmd_snapshot!(cmd, @r" + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--exit-non-zero-on-fix") + .arg("main.py"), @r" success: false exit_code: 1 ----- stdout ----- @@ -782,7 +711,10 @@ if __name__ == "__main__": "); // Second format should exit with code 0 since no files needed formatting - assert_cmd_snapshot!(cmd, @r" + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .arg("--exit-non-zero-on-fix") + .arg("main.py"), @r" success: true exit_code: 0 ----- stdout ----- @@ -796,58 +728,48 @@ if __name__ == "__main__": #[test] fn force_exclude() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" extend-exclude = ["out"] [format] exclude = ["test.py", "generated.py"] "#, - )?; - - fs::write( - tempdir.path().join("main.py"), - r#" + ), + ( + "main.py", + r#" from test import say_hy if __name__ == "__main__": say_hy("dear Ruff contributor") "#, - )?; - - // Excluded file but passed to the CLI directly, should be formatted - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + // Excluded file but passed to the CLI directly, should be formatted + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; - - fs::write( - tempdir.path().join("generated.py"), - r#"NUMBERS = [ + ), + ( + "generated.py", + r#"NUMBERS = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ] OTHER = "OTHER" "#, - )?; + ), + ("out/a.py", "a = a"), + ])?; - let out_dir = tempdir.path().join("out"); - fs::create_dir(&out_dir)?; - - fs::write(out_dir.join("a.py"), "a = a")?; - - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--no-cache", "--force-exclude", "--check", "--config"]) - .arg(ruff_toml.file_name().unwrap()) - // Explicitly pass test.py, should be respect the `format.exclude` when `--force-exclude` is present - .arg(test_path.file_name().unwrap()) + assert_cmd_snapshot!(test.format_command() + .args(["--force-exclude", "--check", "--config", "ruff.toml"]) + // Explicitly pass test.py, should not be formatted because of --force-exclude + .arg("test.py") // Format all other files in the directory, should respect the `exclude` and `format.exclude` options .arg("."), @r" success: false @@ -863,10 +785,8 @@ OTHER = "OTHER" #[test] fn exclude_stdin() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r#" extend-select = ["B", "Q"] ignore = ["Q000", "Q001", "Q002", "Q003"] @@ -876,9 +796,8 @@ exclude = ["generated.py"] "#, )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--config", &ruff_toml.file_name().unwrap().to_string_lossy(), "--stdin-filename", "generated.py", "-"]) + assert_cmd_snapshot!(test.format_command() + .args(["--config", "ruff.toml", "--stdin-filename", "generated.py", "-"]) .pass_stdin(r#" from test import say_hy @@ -903,10 +822,8 @@ if __name__ == '__main__': #[test] fn force_exclude_stdin() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r#" extend-select = ["B", "Q"] ignore = ["Q000", "Q001", "Q002", "Q003"] @@ -916,9 +833,8 @@ exclude = ["generated.py"] "#, )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .args(["format", "--config", &ruff_toml.file_name().unwrap().to_string_lossy(), "--stdin-filename", "generated.py", "--force-exclude", "-"]) + assert_cmd_snapshot!(test.format_command() + .args(["--config", "ruff.toml", "--stdin-filename", "generated.py", "--force-exclude", "-"]) .pass_stdin(r#" from test import say_hy @@ -944,12 +860,10 @@ if __name__ == '__main__': #[test] fn format_option_inheritance() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - let base_toml = tempdir.path().join("base.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" extend = "base.toml" [lint] @@ -958,19 +872,19 @@ extend-select = ["COM812"] [format] quote-style = "single" "#, - )?; - - fs::write( - base_toml, - r#" + ), + ( + "base.toml", + r#" [format] indent-style = "tab" "#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config"]) - .arg(&ruff_toml) + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -1003,91 +917,79 @@ if condition: #[test] fn deprecated_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r" tab-size = 2 ", )?; - insta::with_settings!({filters => vec![ - (&*regex::escape(ruff_toml.to_str().unwrap()), "[RUFF-TOML-PATH]"), - ]}, { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config"]) - .arg(&ruff_toml) + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") .arg("-") .pass_stdin(r" if True: pass "), @r" - success: false - exit_code: 2 - ----- stdout ----- + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` + Cause: Failed to parse [TMP]/ruff.toml + Cause: TOML parse error at line 1, column 1 + | + 1 | + | ^ + unknown field `tab-size` + "); - ----- stderr ----- - ruff failed - Cause: Failed to load configuration `[RUFF-TOML-PATH]` - Cause: Failed to parse [RUFF-TOML-PATH] - Cause: TOML parse error at line 1, column 1 - | - 1 | - | ^ - unknown field `tab-size` - "); - }); Ok(()) } /// Since 0.1.0 the legacy format option is no longer supported #[test] fn legacy_format_option() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r#" format = "json" "#, )?; - insta::with_settings!({filters => vec![ - (&*regex::escape(ruff_toml.to_str().unwrap()), "[RUFF-TOML-PATH]"), - ]}, { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + assert_cmd_snapshot!(test.command() .args(["check", "--select", "F401", "--no-cache", "--config"]) - .arg(&ruff_toml) + .arg("ruff.toml") .arg("-") .pass_stdin(r" import os "), @r#" - success: false - exit_code: 2 - ----- stdout ----- + success: false + exit_code: 2 + ----- stdout ----- - ----- stderr ----- - ruff failed - Cause: Failed to load configuration `[RUFF-TOML-PATH]` - Cause: Failed to parse [RUFF-TOML-PATH] - Cause: TOML parse error at line 2, column 10 - | - 2 | format = "json" - | ^^^^^^ - invalid type: string "json", expected struct FormatOptions - "#); - }); + ----- stderr ----- + ruff failed + Cause: Failed to load configuration `[TMP]/ruff.toml` + Cause: Failed to parse [TMP]/ruff.toml + Cause: TOML parse error at line 2, column 10 + | + 2 | format = "json" + | ^^^^^^ + invalid type: string "json", expected struct FormatOptions + "#); Ok(()) } #[test] fn conflicting_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" indent-width = 2 [lint] @@ -1113,20 +1015,19 @@ allow-multiline = false skip-magic-trailing-comma = true indent-style = "tab" "#, - )?; - - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--no-cache", "--config"]) - .arg(&ruff_toml) - .arg(test_path), @r#" + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") + .arg("test.py"), @r#" success: true exit_code: 0 ----- stdout ----- @@ -1150,10 +1051,8 @@ def say_hy(name: str): #[test] fn conflicting_options_stdin() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, + let test = CliTest::with_file( + "ruff.toml", r#" indent-width = 2 @@ -1179,9 +1078,9 @@ indent-style = "tab" "#, )?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--config"]) - .arg(&ruff_toml) + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") .arg("-") .pass_stdin(r#" def say_hy(name: str): @@ -1209,11 +1108,10 @@ def say_hy(name: str): #[test] fn valid_linter_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" [lint] select = ["ALL"] ignore = ["D203", "D212", "COM812", "ISC001"] @@ -1234,20 +1132,19 @@ multiline-quotes = "double" skip-magic-trailing-comma = false quote-style = "single" "#, - )?; - - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--no-cache", "--config"]) - .arg(&ruff_toml) - .arg(test_path), @r" + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") + .arg("test.py"), @r" success: true exit_code: 0 ----- stdout ----- @@ -1260,11 +1157,10 @@ def say_hy(name: str): #[test] fn valid_linter_options_preserve() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" [lint] select = ["Q"] @@ -1276,20 +1172,19 @@ multiline-quotes = "single" [format] quote-style = "preserve" "#, - )?; - - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--no-cache", "--config"]) - .arg(&ruff_toml) - .arg(test_path), @r" + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") + .arg("test.py"), @r" success: true exit_code: 0 ----- stdout ----- @@ -1302,29 +1197,26 @@ def say_hy(name: str): #[test] fn all_rules_default_options() -> Result<()> { - let tempdir = TempDir::new()?; - let ruff_toml = tempdir.path().join("ruff.toml"); - - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" [lint] select = ["ALL"] "#, - )?; - - let test_path = tempdir.path().join("test.py"); - fs::write( - &test_path, - r#" + ), + ( + "test.py", + r#" def say_hy(name: str): print(f"Hy {name}")"#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--no-cache", "--config"]) - .arg(&ruff_toml) - .arg(test_path), @r" + assert_cmd_snapshot!(test.format_command() + .arg("--config") + .arg("ruff.toml") + .arg("test.py"), @r" success: true exit_code: 0 ----- stdout ----- @@ -1339,117 +1231,116 @@ def say_hy(name: str): } #[test] -fn test_diff() { - let args = ["format", "--no-cache", "--isolated", "--diff"]; - let fixtures = Path::new("resources").join("test").join("fixtures"); +fn test_diff() -> Result<()> { + let crate_root = Path::new(env!("CARGO_MANIFEST_DIR")); + let test = CliTest::with_settings(|_, mut settings| { + settings.add_filter(&tempdir_filter(crate_root.to_str().unwrap()), "CRATE_ROOT/"); + settings + })?; + let fixtures = crate_root.join("resources").join("test").join("fixtures"); let paths = [ fixtures.join("unformatted.py"), fixtures.join("formatted.py"), fixtures.join("unformatted.ipynb"), ]; - insta::with_settings!({filters => vec![ - // Replace windows paths - (r"\\", "/"), - ]}, { - assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)).args(args).args(paths), - @r" - success: false - exit_code: 1 - ----- stdout ----- - --- resources/test/fixtures/unformatted.ipynb:cell 1 - +++ resources/test/fixtures/unformatted.ipynb:cell 1 - @@ -1,3 +1,4 @@ - import numpy - -maths = (numpy.arange(100)**2).sum() - -stats= numpy.asarray([1,2,3,4]).median() - + - +maths = (numpy.arange(100) ** 2).sum() - +stats = numpy.asarray([1, 2, 3, 4]).median() - --- resources/test/fixtures/unformatted.ipynb:cell 3 - +++ resources/test/fixtures/unformatted.ipynb:cell 3 - @@ -1,4 +1,6 @@ - # A cell with IPython escape command - def some_function(foo, bar): - pass - + - + - %matplotlib inline - --- resources/test/fixtures/unformatted.ipynb:cell 4 - +++ resources/test/fixtures/unformatted.ipynb:cell 4 - @@ -1,5 +1,10 @@ + + assert_cmd_snapshot!( + test.format_command().args(["--isolated", "--diff"]).args(paths), + @r" + success: false + exit_code: 1 + ----- stdout ----- + --- CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 1 + +++ CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 1 + @@ -1,3 +1,4 @@ + import numpy + -maths = (numpy.arange(100)**2).sum() + -stats= numpy.asarray([1,2,3,4]).median() + + + +maths = (numpy.arange(100) ** 2).sum() + +stats = numpy.asarray([1, 2, 3, 4]).median() + --- CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 3 + +++ CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 3 + @@ -1,4 +1,6 @@ + # A cell with IPython escape command + def some_function(foo, bar): + pass + + + + + %matplotlib inline + --- CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 4 + +++ CRATE_ROOT/resources/test/fixtures/unformatted.ipynb:cell 4 + @@ -1,5 +1,10 @@ + foo = %pwd + -def some_function(foo,bar,): + + + + + +def some_function( + + foo, + + bar, + +): + # Another cell with IPython escape command foo = %pwd - -def some_function(foo,bar,): - + - + - +def some_function( - + foo, - + bar, - +): - # Another cell with IPython escape command - foo = %pwd - print(foo) + print(foo) - --- resources/test/fixtures/unformatted.py - +++ resources/test/fixtures/unformatted.py - @@ -1,3 +1,3 @@ - x = 1 - -y=2 - +y = 2 - z = 3 + --- CRATE_ROOT/resources/test/fixtures/unformatted.py + +++ CRATE_ROOT/resources/test/fixtures/unformatted.py + @@ -1,3 +1,3 @@ + x = 1 + -y=2 + +y = 2 + z = 3 - ----- stderr ----- - 2 files would be reformatted, 1 file already formatted - "); - }); + ----- stderr ----- + 2 files would be reformatted, 1 file already formatted + "); + + Ok(()) } #[test] -fn test_diff_no_change() { - let args = ["format", "--no-cache", "--isolated", "--diff"]; - let fixtures = Path::new("resources").join("test").join("fixtures"); +fn test_diff_no_change() -> Result<()> { + let crate_root = Path::new(env!("CARGO_MANIFEST_DIR")); + let test = CliTest::with_settings(|_, mut settings| { + settings.add_filter(&tempdir_filter(crate_root.to_str().unwrap()), "CRATE_ROOT/"); + settings + })?; + + let fixtures = crate_root.join("resources").join("test").join("fixtures"); let paths = [fixtures.join("unformatted.py")]; - insta::with_settings!({filters => vec![ - // Replace windows paths - (r"\\", "/"), - ]}, { - assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)).args(args).args(paths), - @r" - success: false - exit_code: 1 - ----- stdout ----- - --- resources/test/fixtures/unformatted.py - +++ resources/test/fixtures/unformatted.py - @@ -1,3 +1,3 @@ - x = 1 - -y=2 - +y = 2 - z = 3 + assert_cmd_snapshot!( + test.format_command().args(["--isolated", "--diff"]).args(paths), + @r" + success: false + exit_code: 1 + ----- stdout ----- + --- CRATE_ROOT/resources/test/fixtures/unformatted.py + +++ CRATE_ROOT/resources/test/fixtures/unformatted.py + @@ -1,3 +1,3 @@ + x = 1 + -y=2 + +y = 2 + z = 3 - ----- stderr ----- - 1 file would be reformatted - " - ); - }); + ----- stderr ----- + 1 file would be reformatted + " + ); + + Ok(()) } #[test] -fn test_diff_stdin_unformatted() { - let args = [ - "format", - "--isolated", - "--diff", - "-", - "--stdin-filename", - "unformatted.py", - ]; +fn test_diff_stdin_unformatted() -> Result<()> { + let test = CliTest::new()?; let fixtures = Path::new("resources").join("test").join("fixtures"); let unformatted = fs::read(fixtures.join("unformatted.py")).unwrap(); assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)).args(args).pass_stdin(unformatted), + test.format_command() + .args(["--isolated", "--diff", "-", "--stdin-filename", "unformatted.py"]) + .pass_stdin(unformatted), @r" success: false exit_code: 1 @@ -1465,15 +1356,16 @@ fn test_diff_stdin_unformatted() { ----- stderr ----- "); + Ok(()) } #[test] -fn test_diff_stdin_formatted() { - let args = ["format", "--isolated", "--diff", "-"]; +fn test_diff_stdin_formatted() -> Result<()> { + let test = CliTest::new()?; let fixtures = Path::new("resources").join("test").join("fixtures"); let unformatted = fs::read(fixtures.join("formatted.py")).unwrap(); assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)).args(args).pass_stdin(unformatted), + test.format_command().args(["--isolated", "--diff", "-"]).pass_stdin(unformatted), @r" success: true exit_code: 0 @@ -1481,14 +1373,17 @@ fn test_diff_stdin_formatted() { ----- stderr ----- "); + Ok(()) } #[test] -fn test_notebook_trailing_semicolon() { +fn test_notebook_trailing_semicolon() -> Result<()> { + let test = CliTest::new()?; + let fixtures = Path::new("resources").join("test").join("fixtures"); let unformatted = fs::read(fixtures.join("trailing_semicolon.ipynb")).unwrap(); - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.ipynb"]) + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.ipynb"]) .arg("-") .pass_stdin(unformatted), @r##" success: true @@ -1910,23 +1805,21 @@ fn test_notebook_trailing_semicolon() { ----- stderr ----- "##); + Ok(()) } #[test] fn syntax_error_in_notebooks() -> Result<()> { - let tempdir = TempDir::new()?; - - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" include = ["*.ipy"] "#, - )?; - - fs::write( - tempdir.path().join("main.ipy"), - r#" + ), + ( + "main.ipy", + r#" { "cells": [ { @@ -1974,13 +1867,11 @@ include = ["*.ipy"] "nbformat_minor": 0 } "#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .arg("format") - .arg("--no-cache") - .args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()]) + assert_cmd_snapshot!(test.format_command() + .args(["--config", "ruff.toml"]) .args(["--extension", "ipy:ipynb"]) .arg("."), @r" success: false @@ -1995,19 +1886,16 @@ include = ["*.ipy"] #[test] fn extension() -> Result<()> { - let tempdir = TempDir::new()?; - - let ruff_toml = tempdir.path().join("ruff.toml"); - fs::write( - &ruff_toml, - r#" + let test = CliTest::with_files([ + ( + "ruff.toml", + r#" include = ["*.ipy"] "#, - )?; - - fs::write( - tempdir.path().join("main.ipy"), - r#" + ), + ( + "main.ipy", + r#" { "cells": [ { @@ -2044,13 +1932,11 @@ include = ["*.ipy"] "nbformat_minor": 5 } "#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .current_dir(tempdir.path()) - .arg("format") - .arg("--no-cache") - .args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()]) + assert_cmd_snapshot!(test.format_command() + .args(["--config", "ruff.toml"]) .args(["--extension", "ipy:ipynb"]) .arg("."), @r" success: true @@ -2064,9 +1950,10 @@ include = ["*.ipy"] } #[test] -fn range_formatting() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=2:8-2:14"]) +fn range_formatting() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=2:8-2:14"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2086,12 +1973,14 @@ def foo(arg1, arg2,): ----- stderr ----- "#); + Ok(()) } #[test] -fn range_formatting_unicode() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=2:21-3"]) +fn range_formatting_unicode() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=2:21-3"]) .arg("-") .pass_stdin(r#" def foo(arg1="👋🏽" ): print("Format this" ) @@ -2105,37 +1994,34 @@ def foo(arg1="👋🏽" ): print("Format this" ) ----- stderr ----- "#); + Ok(()) } #[test] -fn range_formatting_multiple_files() -> std::io::Result<()> { - let tempdir = TempDir::new()?; - let file1 = tempdir.path().join("file1.py"); - - fs::write( - &file1, - r#" +fn range_formatting_multiple_files() -> Result<()> { + let test = CliTest::with_files([ + ( + "file1.py", + r#" def file1(arg1, arg2,): print("Shouldn't format this" ) "#, - )?; - - let file2 = tempdir.path().join("file2.py"); - - fs::write( - &file2, - r#" + ), + ( + "file2.py", + r#" def file2(arg1, arg2,): print("Shouldn't format this" ) "#, - )?; + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--range=1:8-1:15"]) - .arg(file1) - .arg(file2), @r" + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--range=1:8-1:15"]) + .arg("file1.py") + .arg("file2.py"), @r" success: false exit_code: 2 ----- stdout ----- @@ -2149,9 +2035,10 @@ def file2(arg1, arg2,): } #[test] -fn range_formatting_out_of_bounds() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=100:40-200:1"]) +fn range_formatting_out_of_bounds() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=100:40-200:1"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2168,12 +2055,14 @@ def foo(arg1, arg2,): ----- stderr ----- "#); + Ok(()) } #[test] -fn range_start_larger_than_end() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=90-50"]) +fn range_start_larger_than_end() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=90-50"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2190,12 +2079,14 @@ def foo(arg1, arg2,): For more information, try '--help'. "); + Ok(()) } #[test] -fn range_line_numbers_only() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=2-3"]) +fn range_line_numbers_only() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=2-3"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2215,12 +2106,14 @@ def foo(arg1, arg2,): ----- stderr ----- "#); + Ok(()) } #[test] -fn range_start_only() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=3"]) +fn range_start_only() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=3"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2236,12 +2129,14 @@ def foo(arg1, arg2,): ----- stderr ----- "#); + Ok(()) } #[test] -fn range_end_only() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=-3"]) +fn range_end_only() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=-3"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2260,12 +2155,14 @@ def foo(arg1, arg2,): ----- stderr ----- "#); + Ok(()) } #[test] -fn range_missing_line() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=1-:20"]) +fn range_missing_line() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=1-:20"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2282,12 +2179,14 @@ def foo(arg1, arg2,): For more information, try '--help'. "); + Ok(()) } #[test] -fn zero_line_number() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=0:2"]) +fn zero_line_number() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=0:2"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2305,12 +2204,14 @@ def foo(arg1, arg2,): For more information, try '--help'. "); + Ok(()) } #[test] -fn column_and_line_zero() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--range=0:0"]) +fn column_and_line_zero() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--range=0:0"]) .arg("-") .pass_stdin(r#" def foo(arg1, arg2,): @@ -2328,12 +2229,14 @@ def foo(arg1, arg2,): For more information, try '--help'. "); + Ok(()) } #[test] -fn range_formatting_notebook() { - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--no-cache", "--stdin-filename", "main.ipynb", "--range=1-2"]) +fn range_formatting_notebook() -> Result<()> { + let test = CliTest::new()?; + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "main.ipynb", "--range=1-2"]) .arg("-") .pass_stdin(r#" { @@ -2379,6 +2282,7 @@ fn range_formatting_notebook() { ----- stderr ----- error: Failed to format main.ipynb: Range formatting isn't supported for notebooks. "); + Ok(()) } /// Test that the formatter respects `per-file-target-version`. Context managers can't be @@ -2386,10 +2290,11 @@ fn range_formatting_notebook() { /// /// Adapted from #[test] -fn per_file_target_version_formatter() { +fn per_file_target_version_formatter() -> Result<()> { + let test = CliTest::new()?; // without `per-file-target-version` this should not be reformatted in the same way - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--target-version=py38"]) + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--stdin-filename", "test.py", "--target-version=py38"]) .arg("-") .pass_stdin(r#" with open("a_really_long_foo") as foo, open("a_really_long_bar") as bar, open("a_really_long_baz") as baz: @@ -2406,8 +2311,9 @@ with open("a_really_long_foo") as foo, open("a_really_long_bar") as bar, open("a ----- stderr ----- "#); - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--isolated", "--stdin-filename", "test.py", "--target-version=py38"]) + assert_cmd_snapshot!(test.format_command() + .arg("--isolated") + .args(["--stdin-filename", "test.py", "--target-version=py38"]) .args(["--config", r#"per-file-target-version = {"test.py" = "py311"}"#]) .arg("-") .pass_stdin(r#" @@ -2426,6 +2332,7 @@ with open("a_really_long_foo") as foo, open("a_really_long_bar") as bar, open("a ----- stderr ----- "#); + Ok(()) } /// Regression test for with very helpful @@ -2436,21 +2343,19 @@ fn cookiecutter_globbing() -> Result<()> { // problem is this `{{cookiecutter.repo_name}}` directory containing a config file with a glob. // The absolute path of the glob contains the glob metacharacters `{{` and `}}` even though the // user's glob does not. - let tempdir = TempDir::new()?; - let cookiecutter = tempdir.path().join("{{cookiecutter.repo_name}}"); - let cookiecutter_toml = cookiecutter.join("pyproject.toml"); - let tests = cookiecutter.join("tests"); - fs::create_dir_all(&tests)?; - fs::write( - cookiecutter_toml, - r#"tool.ruff.lint.per-file-ignores = { "tests/*" = ["F811"] }"#, - )?; - let maintest = tests.join("maintest.py"); - fs::write(maintest, "import foo\nimport bar\nimport foo\n")?; + let test = CliTest::with_files([ + ( + "{{cookiecutter.repo_name}}/pyproject.toml", + r#"tool.ruff.lint.per-file-ignores = { "tests/*" = ["F811"] }"#, + ), + ( + "{{cookiecutter.repo_name}}/tests/maintest.py", + "import foo\nimport bar\nimport foo\n", + ), + ])?; - assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--no-cache", "--diff"]) - .current_dir(tempdir.path()), @r" + assert_cmd_snapshot!(test.format_command() + .args(["--isolated", "--diff", "."]), @r" success: true exit_code: 0 ----- stdout ----- @@ -2463,19 +2368,20 @@ fn cookiecutter_globbing() -> Result<()> { } #[test] -fn stable_output_format_warning() { +fn stable_output_format_warning() -> Result<()> { + let test = CliTest::new()?; assert_cmd_snapshot!( - Command::new(get_cargo_bin(BIN_NAME)) - .args(["format", "--output-format=full", "-"]) - .pass_stdin("1"), + test.format_command() + .args(["--output-format=full", "-"]) + .pass_stdin(""), @r" success: true exit_code: 0 ----- stdout ----- - 1 ----- stderr ----- warning: The --output-format flag for the formatter is unstable and requires preview mode to use. ", ); + Ok(()) } diff --git a/crates/ruff/tests/cli/main.rs b/crates/ruff/tests/cli/main.rs index 91f3704e4c..ef7313253e 100644 --- a/crates/ruff/tests/cli/main.rs +++ b/crates/ruff/tests/cli/main.rs @@ -15,6 +15,7 @@ use std::{ }; use tempfile::TempDir; +mod format; mod lint; const BIN_NAME: &str = "ruff"; @@ -57,6 +58,16 @@ impl CliTest { Self::with_settings(|_, settings| settings) } + pub(crate) fn with_files<'a>( + files: impl IntoIterator, + ) -> anyhow::Result { + let case = Self::new()?; + for file in files { + case.write_file(file.0, file.1)?; + } + Ok(case) + } + pub(crate) fn with_settings( setup_settings: impl FnOnce(&Path, insta::Settings) -> insta::Settings, ) -> Result { @@ -174,4 +185,10 @@ impl CliTest { command } + + pub(crate) fn format_command(&self) -> Command { + let mut command = self.command(); + command.args(["format", "--no-cache"]); + command + } } diff --git a/crates/ruff/tests/snapshots/format__output_format_azure.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_azure.snap similarity index 89% rename from crates/ruff/tests/snapshots/format__output_format_azure.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_azure.snap index f27a327727..c6401871ae 100644 --- a/crates/ruff/tests/snapshots/format__output_format_azure.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_azure.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_concise.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_concise.snap similarity index 88% rename from crates/ruff/tests/snapshots/format__output_format_concise.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_concise.snap index 8a24633768..6e220438c0 100644 --- a/crates/ruff/tests/snapshots/format__output_format_concise.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_concise.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_full.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_full.snap similarity index 90% rename from crates/ruff/tests/snapshots/format__output_format_full.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_full.snap index 30eb3a0a51..e48f0b5563 100644 --- a/crates/ruff/tests/snapshots/format__output_format_full.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_full.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_github.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_github.snap similarity index 90% rename from crates/ruff/tests/snapshots/format__output_format_github.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_github.snap index e279ad2b87..92086762b5 100644 --- a/crates/ruff/tests/snapshots/format__output_format_github.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_github.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_gitlab.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_gitlab.snap similarity index 93% rename from crates/ruff/tests/snapshots/format__output_format_gitlab.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_gitlab.snap index fbf68871d3..7b0802de73 100644 --- a/crates/ruff/tests/snapshots/format__output_format_gitlab.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_gitlab.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_grouped.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_grouped.snap similarity index 83% rename from crates/ruff/tests/snapshots/format__output_format_grouped.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_grouped.snap index bd9ec0e7e4..60482d5075 100644 --- a/crates/ruff/tests/snapshots/format__output_format_grouped.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_grouped.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: @@ -7,6 +7,7 @@ info: - "--no-cache" - "--output-format" - grouped + - "--preview" - "--check" - input.py --- diff --git a/crates/ruff/tests/snapshots/format__output_format_json-lines.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_json-lines.snap similarity index 93% rename from crates/ruff/tests/snapshots/format__output_format_json-lines.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_json-lines.snap index dadde72435..10c4622041 100644 --- a/crates/ruff/tests/snapshots/format__output_format_json-lines.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_json-lines.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_json.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_json.snap similarity index 95% rename from crates/ruff/tests/snapshots/format__output_format_json.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_json.snap index 1bbff05aec..e1058c41b1 100644 --- a/crates/ruff/tests/snapshots/format__output_format_json.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_json.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_junit.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_junit.snap similarity index 94% rename from crates/ruff/tests/snapshots/format__output_format_junit.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_junit.snap index 518c836729..221b908122 100644 --- a/crates/ruff/tests/snapshots/format__output_format_junit.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_junit.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_pylint.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_pylint.snap similarity index 81% rename from crates/ruff/tests/snapshots/format__output_format_pylint.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_pylint.snap index 7d5f80fed4..6400bdf265 100644 --- a/crates/ruff/tests/snapshots/format__output_format_pylint.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_pylint.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: @@ -7,6 +7,7 @@ info: - "--no-cache" - "--output-format" - pylint + - "--preview" - "--check" - input.py --- diff --git a/crates/ruff/tests/snapshots/format__output_format_rdjson.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_rdjson.snap similarity index 96% rename from crates/ruff/tests/snapshots/format__output_format_rdjson.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_rdjson.snap index dcdb5bda8c..b9d6dcdce3 100644 --- a/crates/ruff/tests/snapshots/format__output_format_rdjson.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_rdjson.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: diff --git a/crates/ruff/tests/snapshots/format__output_format_sarif.snap b/crates/ruff/tests/cli/snapshots/cli__format__output_format_sarif.snap similarity index 97% rename from crates/ruff/tests/snapshots/format__output_format_sarif.snap rename to crates/ruff/tests/cli/snapshots/cli__format__output_format_sarif.snap index 1f31ab0374..e6373198ac 100644 --- a/crates/ruff/tests/snapshots/format__output_format_sarif.snap +++ b/crates/ruff/tests/cli/snapshots/cli__format__output_format_sarif.snap @@ -1,5 +1,5 @@ --- -source: crates/ruff/tests/format.rs +source: crates/ruff/tests/cli/format.rs info: program: ruff args: