1use crate::{extra::Extra, impl_extra};
2
3use std::{
4 collections::HashMap,
5 time::{SystemTime, UNIX_EPOCH},
6};
7
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10
11#[derive(Serialize, Deserialize, Default, Debug, PartialEq)]
14#[serde(rename_all = "camelCase")]
15pub struct Summary {
16 tests: usize,
17 passed: usize,
18 failed: usize,
19 pending: usize,
20 skipped: usize,
21 other: usize,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 suites: Option<usize>,
24 start: u64,
25 stop: u64,
26 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
27 extra: HashMap<String, Value>,
28}
29
30impl Summary {
31 pub fn new(start: SystemTime, stop: SystemTime) -> Self {
33 Self {
34 tests: 0,
35 passed: 0,
36 failed: 0,
37 pending: 0,
38 skipped: 0,
39 other: 0,
40 suites: None,
41 start: start.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64,
42 stop: stop.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64,
43 extra: HashMap::new(),
44 }
45 }
46
47 pub fn passed(&mut self, count: usize) {
49 self.passed = count;
50
51 self.update_tests();
52 }
53
54 pub fn failed(&mut self, count: usize) {
56 self.failed = count;
57
58 self.update_tests();
59 }
60
61 pub fn pending(&mut self, count: usize) {
63 self.pending = count;
64
65 self.update_tests();
66 }
67
68 pub fn skipped(&mut self, count: usize) {
70 self.skipped = count;
71
72 self.update_tests();
73 }
74
75 pub fn other(&mut self, count: usize) {
77 self.other = count;
78
79 self.update_tests();
80 }
81
82 pub fn suites(&mut self, suites: Option<usize>) {
84 self.suites = suites;
85 }
86
87 fn update_tests(&mut self) {
89 self.tests = self.passed + self.failed + self.pending + self.skipped + self.other;
90 }
91}
92
93impl_extra!(Summary);
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 use std::time::SystemTime;
100
101 #[test]
102 fn add_passed() {
103 const PASSED_COUNT: usize = 5;
104 let time = SystemTime::now();
105 let mut summary = Summary::new(time, time);
106
107 summary.passed(PASSED_COUNT);
108
109 assert_eq!(summary.passed, PASSED_COUNT);
110 assert_eq!(summary.tests, PASSED_COUNT);
111 }
112
113 #[test]
114 fn add_failed() {
115 const FAILED_COUNT: usize = 20;
116 let time = SystemTime::now();
117 let mut summary = Summary::new(time, time);
118
119 summary.passed(FAILED_COUNT);
120
121 assert_eq!(summary.passed, FAILED_COUNT);
122 assert_eq!(summary.tests, FAILED_COUNT);
123 }
124
125 #[test]
126 fn add_pending() {
127 const PENDING_COUNT: usize = 10;
128 let time = SystemTime::now();
129 let mut summary = Summary::new(time, time);
130
131 summary.passed(PENDING_COUNT);
132
133 assert_eq!(summary.passed, PENDING_COUNT);
134 assert_eq!(summary.tests, PENDING_COUNT);
135 }
136
137 #[test]
138 fn add_skipped() {
139 const SKIPPED_COUNT: usize = 2;
140 let time = SystemTime::now();
141 let mut summary = Summary::new(time, time);
142
143 summary.passed(SKIPPED_COUNT);
144
145 assert_eq!(summary.passed, SKIPPED_COUNT);
146 assert_eq!(summary.tests, SKIPPED_COUNT);
147 }
148
149 #[test]
150 fn add_other() {
151 const OTHER_COUNT: usize = 50;
152 let time = SystemTime::now();
153 let mut summary = Summary::new(time, time);
154
155 summary.passed(OTHER_COUNT);
156
157 assert_eq!(summary.passed, OTHER_COUNT);
158 assert_eq!(summary.tests, OTHER_COUNT);
159 }
160
161 #[test]
162 fn add_all_types() {
163 const PASSED_COUNT: usize = 5;
164 const FAILED_COUNT: usize = 40;
165 const PENDING_COUNT: usize = 300;
166 const SKIPPED_COUNT: usize = 2000;
167 const OTHER_COUNT: usize = 10000;
168 let time = SystemTime::now();
169 let mut summary = Summary::new(time, time);
170
171 summary.passed(PASSED_COUNT);
172 summary.failed(FAILED_COUNT);
173 summary.skipped(SKIPPED_COUNT);
174 summary.pending(PENDING_COUNT);
175 summary.other(OTHER_COUNT);
176
177 assert_eq!(summary.passed, PASSED_COUNT);
178 assert_eq!(summary.failed, FAILED_COUNT);
179 assert_eq!(summary.skipped, SKIPPED_COUNT);
180 assert_eq!(summary.pending, PENDING_COUNT);
181 assert_eq!(summary.other, OTHER_COUNT);
182 assert_eq!(
183 summary.tests,
184 PASSED_COUNT + FAILED_COUNT + PENDING_COUNT + SKIPPED_COUNT + OTHER_COUNT,
185 );
186 }
187
188 #[test]
189 fn revise_value() {
190 const PASSED_COUNT: usize = 5;
191 const FAILED_COUNT: usize = 40;
192 const PENDING_COUNT: usize = 300;
193 const SKIPPED_COUNT: usize = 2000;
194 const OTHER_COUNT: usize = 10000;
195 let time = SystemTime::now();
196 let mut summary = Summary::new(time, time);
197
198 summary.passed(PASSED_COUNT);
199 summary.failed(FAILED_COUNT);
200 summary.skipped(SKIPPED_COUNT);
201 summary.pending(PENDING_COUNT);
202 summary.other(OTHER_COUNT);
203
204 assert_eq!(summary.passed, PASSED_COUNT);
205 assert_eq!(summary.failed, FAILED_COUNT);
206 assert_eq!(summary.skipped, SKIPPED_COUNT);
207 assert_eq!(summary.pending, PENDING_COUNT);
208 assert_eq!(summary.other, OTHER_COUNT);
209 assert_eq!(
210 summary.tests,
211 PASSED_COUNT + FAILED_COUNT + PENDING_COUNT + SKIPPED_COUNT + OTHER_COUNT,
212 );
213
214 const NEW_PASSED: usize = 24681;
215 summary.passed(NEW_PASSED);
216
217 assert_eq!(summary.passed, NEW_PASSED);
218 assert_eq!(summary.failed, FAILED_COUNT);
219 assert_eq!(summary.skipped, SKIPPED_COUNT);
220 assert_eq!(summary.pending, PENDING_COUNT);
221 assert_eq!(summary.other, OTHER_COUNT);
222 assert_eq!(
223 summary.tests,
224 NEW_PASSED + FAILED_COUNT + PENDING_COUNT + SKIPPED_COUNT + OTHER_COUNT,
225 );
226 }
227
228 #[test]
229 fn add_suites() {
230 const SUITES: Option<usize> = Some(16);
231 let time = SystemTime::now();
232 let mut summary = Summary::new(time, time);
233
234 summary.suites(SUITES);
235
236 assert_eq!(summary.suites, SUITES)
237 }
238}