diff --git a/Cargo.lock b/Cargo.lock index df14e77427054..2e586d7220f80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2134,6 +2134,7 @@ name = "red_knot_test" version = "0.0.0" dependencies = [ "anyhow", + "colored", "once_cell", "red_knot_python_semantic", "red_knot_vendored", diff --git a/crates/red_knot_test/Cargo.toml b/crates/red_knot_test/Cargo.toml index 88059cb0e265a..5fcc0b9143edb 100644 --- a/crates/red_knot_test/Cargo.toml +++ b/crates/red_knot_test/Cargo.toml @@ -20,6 +20,7 @@ ruff_source_file = { workspace = true } ruff_text_size = { workspace = true } anyhow = { workspace = true } +colored = { workspace = true } once_cell = { workspace = true } regex = { workspace = true } rustc-hash = { workspace = true } diff --git a/crates/red_knot_test/src/lib.rs b/crates/red_knot_test/src/lib.rs index 2d05e6283ab01..688b906ac09d0 100644 --- a/crates/red_knot_test/src/lib.rs +++ b/crates/red_knot_test/src/lib.rs @@ -1,3 +1,4 @@ +use colored::Colorize; use parser as test_parser; use red_knot_python_semantic::types::check_types; use ruff_db::files::system_path_to_file; @@ -31,13 +32,14 @@ pub fn run(path: &PathBuf, title: &str) { for test in suite.tests() { if let Err(failures) = run_test(&test) { any_failures = true; - println!("{}", test.name()); + println!("\n{}\n", test.name().bold().underline()); for (path, by_line) in failures { - println!(" {path}"); - for (line, failures) in by_line.iter() { + println!("{}", path.as_str().bold()); + for (line_number, failures) in by_line.iter() { for failure in failures { - println!(" line {line}: {failure}"); + let line_info = format!("line {line_number}:").cyan(); + println!(" {line_info} {failure}"); } } println!(); @@ -45,6 +47,8 @@ pub fn run(path: &PathBuf, title: &str) { } } + println!("{}\n", "-".repeat(50)); + assert!(!any_failures, "Some tests failed."); } diff --git a/crates/red_knot_test/src/matcher.rs b/crates/red_knot_test/src/matcher.rs index 24defb94be0a7..fbc3d9ba7739d 100644 --- a/crates/red_knot_test/src/matcher.rs +++ b/crates/red_knot_test/src/matcher.rs @@ -3,6 +3,7 @@ use crate::assertion::{Assertion, ErrorAssertion, InlineFileAssertions}; use crate::db::Db; use crate::diagnostic::SortedDiagnostics; +use colored::Colorize; use red_knot_python_semantic::types::TypeCheckDiagnostic; use ruff_db::files::File; use ruff_db::source::{line_index, source_text, SourceText}; @@ -155,7 +156,7 @@ trait UnmatchedWithColumn { impl Unmatched for Assertion<'_> { fn unmatched(&self) -> String { - format!("unmatched assertion: {self}") + format!("{} {self}", "unmatched assertion:".red()) } } @@ -165,11 +166,11 @@ fn maybe_add_undefined_reveal_clarification( ) -> String { if diagnostic.rule() == "undefined-reveal" { format!( - "used built-in `reveal_type`: add a `# revealed` assertion on this line \ - (original diagnostic: {original})" + "{} add a `# revealed` assertion on this line (original diagnostic: {original})", + "used built-in `reveal_type`:".yellow() ) } else { - format!("unexpected error: {original}") + format!("{} {original}", "unexpected error:".red()) } } @@ -232,7 +233,10 @@ impl Matcher { .. }) ) { - failures.push("invalid assertion: no rule or message text".to_string()); + failures.push(format!( + "{} no rule or message text", + "invalid assertion:".red() + )); continue; } if !self.matches(assertion, &mut unmatched) { @@ -360,6 +364,8 @@ mod tests { } fn get_result(source: &str, diagnostics: Vec) -> Result<(), FailuresByLine> { + colored::control::set_override(false); + let mut db = crate::db::Db::setup(SystemPathBuf::from("/src")); db.write_file("/src/test.py", source).unwrap(); let file = system_path_to_file(&db, "/src/test.py").unwrap();