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