libtest2_harness/notify/
summary.rs1use super::Event;
2use super::RunStatus;
3use super::FAILED;
4use super::OK;
5
6#[derive(Default, Clone, Debug)]
7pub(crate) struct Summary {
8 pub(crate) failures: std::collections::BTreeMap<String, Option<String>>,
9 pub(crate) elapsed_s: super::Elapsed,
10
11 pub(crate) num_run: usize,
12 pub(crate) num_filtered_out: usize,
15
16 pub(crate) num_passed: usize,
18 pub(crate) num_failed: usize,
20 pub(crate) num_ignored: usize,
22}
23
24impl Summary {
25 pub(crate) fn has_failed(&self) -> bool {
26 0 < self.num_failed
27 }
28
29 pub(crate) fn write_start(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> {
30 let s = if self.num_run == 1 { "" } else { "s" };
31
32 writeln!(writer)?;
33 writeln!(writer, "running {} test{s}", self.num_run)?;
34 Ok(())
35 }
36
37 pub(crate) fn write_complete(&self, writer: &mut dyn ::std::io::Write) -> std::io::Result<()> {
38 let (summary, summary_style) = if self.has_failed() {
39 ("FAILED", FAILED)
40 } else {
41 ("ok", OK)
42 };
43 let num_passed = self.num_passed;
44 let num_failed = self.num_failed;
45 let num_ignored = self.num_ignored;
46 let num_filtered_out = self.num_filtered_out;
47 let elapsed_s = self.elapsed_s;
48
49 if self.has_failed() {
50 writeln!(writer)?;
51 writeln!(writer, "failures:")?;
52 writeln!(writer)?;
53
54 for (name, msg) in &self.failures {
56 if let Some(msg) = msg {
57 writeln!(writer, "---- {name} ----")?;
58 writeln!(writer, "{msg}")?;
59 writeln!(writer)?;
60 }
61 }
62
63 writeln!(writer)?;
65 writeln!(writer, "failures:")?;
66 for name in self.failures.keys() {
67 writeln!(writer, " {name}")?;
68 }
69 }
70 writeln!(writer)?;
71 writeln!(
72 writer,
73 "test result: {summary_style}{summary}{summary_style:#}. {num_passed} passed; {num_failed} failed; {num_ignored} ignored; \
74 {num_filtered_out} filtered out; finished in {elapsed_s}",
75 )?;
76 writeln!(writer)?;
77
78 Ok(())
79 }
80}
81
82impl super::Notifier for Summary {
83 fn notify(&mut self, event: Event) -> std::io::Result<()> {
84 match event {
85 Event::DiscoverStart => {}
86 Event::DiscoverCase { run, .. } => {
87 if run {
88 self.num_run += 1;
89 } else {
90 self.num_filtered_out += 1;
91 }
92 }
93 Event::DiscoverComplete { .. } => {}
94 Event::SuiteStart => {}
95 Event::CaseStart { .. } => {}
96 Event::CaseComplete {
97 name,
98 status,
99 message,
100 ..
101 } => match status {
102 Some(RunStatus::Ignored) => {
103 self.num_ignored += 1;
104 }
105 Some(RunStatus::Failed) => {
106 self.num_failed += 1;
107 self.failures.insert(name, message);
108 }
109 None => {
110 self.num_passed += 1;
111 }
112 },
113 Event::SuiteComplete { elapsed_s, .. } => {
114 self.elapsed_s = elapsed_s;
115 }
116 }
117 Ok(())
118 }
119}