about summary refs log tree commit diff
path: root/library/test/src
diff options
context:
space:
mode:
authorjyn <github@jyn.dev>2023-11-04 21:40:38 -0400
committerjyn <github@jyn.dev>2024-03-04 21:45:41 -0500
commit8bfe9dbae20628bfcea390556c40a991984692ec (patch)
treec7084058487883bc60e80899bbe9361ce77fa0eb /library/test/src
parent678e2177dcc089bb5355819d11ee22d7703126d4 (diff)
libtest: Print the names of failed tests eagerly
Previously, libtest would wait until all tests finished running to print the progress, which made it
annoying to run many tests at once (since you don't know which have failed). Change it to print the
names as soon as they fail.

This also adds a test for the terse output; previously it was untested.
Diffstat (limited to 'library/test/src')
-rw-r--r--library/test/src/formatters/terse.rs35
1 files changed, 28 insertions, 7 deletions
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 2931ca6ead0..22c28e4954e 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -23,6 +23,7 @@ pub(crate) struct TerseFormatter<T> {
     max_name_len: usize,
 
     test_count: usize,
+    test_column: usize,
     total_test_count: usize,
 }
 
@@ -39,6 +40,7 @@ impl<T: Write> TerseFormatter<T> {
             max_name_len,
             is_multithreaded,
             test_count: 0,
+            test_column: 0,
             total_test_count: 0, // initialized later, when write_run_start is called
         }
     }
@@ -47,8 +49,20 @@ impl<T: Write> TerseFormatter<T> {
         self.write_short_result(".", term::color::GREEN)
     }
 
-    pub fn write_failed(&mut self) -> io::Result<()> {
-        self.write_short_result("F", term::color::RED)
+    pub fn write_failed(&mut self, name: &str) -> io::Result<()> {
+        // Put failed tests on their own line and include the test name, so that it's faster
+        // to see which test failed without having to wait for them all to run.
+
+        // normally, we write the progress unconditionally, even if the previous line was cut short.
+        // but if this is the very first column, no short results will have been printed and we'll end up with *only* the progress on the line.
+        // avoid this.
+        if self.test_column != 0 {
+            self.write_progress()?;
+        }
+        self.test_count += 1;
+        self.write_plain(format!("{name} --- "))?;
+        self.write_pretty("FAILED", term::color::RED)?;
+        self.write_plain("\n")
     }
 
     pub fn write_ignored(&mut self) -> io::Result<()> {
@@ -65,15 +79,22 @@ impl<T: Write> TerseFormatter<T> {
         color: term::color::Color,
     ) -> io::Result<()> {
         self.write_pretty(result, color)?;
-        if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
+        self.test_count += 1;
+        self.test_column += 1;
+        if self.test_column % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
             // We insert a new line regularly in order to flush the
             // screen when dealing with line-buffered output (e.g., piping to
             // `stamp` in the rust CI).
-            let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count);
-            self.write_plain(out)?;
+            self.write_progress()?;
         }
 
-        self.test_count += 1;
+        Ok(())
+    }
+
+    fn write_progress(&mut self) -> io::Result<()> {
+        let out = format!(" {}/{}\n", self.test_count, self.total_test_count);
+        self.write_plain(out)?;
+        self.test_column = 0;
         Ok(())
     }
 
@@ -213,7 +234,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
         match *result {
             TestResult::TrOk => self.write_ok(),
             TestResult::TrFailed | TestResult::TrFailedMsg(_) | TestResult::TrTimedFail => {
-                self.write_failed()
+                self.write_failed(desc.name.as_slice())
             }
             TestResult::TrIgnored => self.write_ignored(),
             TestResult::TrBench(ref bs) => {