@@ -22,6 +22,7 @@ pub struct IntegrationTests {
22
22
total : i64 ,
23
23
passed : i64 ,
24
24
skipped : i64 ,
25
+ failed_list : Vec < String > ,
25
26
focus_run : bool ,
26
27
}
27
28
@@ -70,6 +71,7 @@ impl IntegrationTests {
70
71
let clock = Instant :: now ( ) ;
71
72
self . run_rust_tests ( rust_tests, scene_tree) ;
72
73
let rust_time = clock. elapsed ( ) ;
74
+
73
75
let gdscript_time = if !focus_run {
74
76
let extra_duration = self . run_gdscript_tests ( gdscript_tests) ;
75
77
Some ( ( clock. elapsed ( ) - rust_time) + extra_duration)
@@ -126,7 +128,7 @@ impl IntegrationTests {
126
128
print_test_pre ( test. name , test. file . to_string ( ) , & mut last_file, false ) ;
127
129
let outcome = run_rust_test ( & test, & ctx) ;
128
130
129
- self . update_stats ( & outcome) ;
131
+ self . update_stats ( & outcome, test . file , test . name ) ;
130
132
print_test_post ( test. name , outcome) ;
131
133
}
132
134
}
@@ -139,7 +141,7 @@ impl IntegrationTests {
139
141
let test_file = get_property ( & test, "suite_name" ) ;
140
142
let test_case = get_property ( & test, "method_name" ) ;
141
143
142
- print_test_pre ( & test_case, test_file, & mut last_file, true ) ;
144
+ print_test_pre ( & test_case, test_file. clone ( ) , & mut last_file, true ) ;
143
145
let result = test. call ( "run" , & [ ] ) ;
144
146
// In case a test needs to disable error messages to ensure it runs properly.
145
147
Engine :: singleton ( ) . set_print_error_messages ( true ) ;
@@ -155,7 +157,7 @@ impl IntegrationTests {
155
157
}
156
158
let outcome = TestOutcome :: from_bool ( success) ;
157
159
158
- self . update_stats ( & outcome) ;
160
+ self . update_stats ( & outcome, & test_file , & test_case ) ;
159
161
print_test_post ( & test_case, outcome) ;
160
162
}
161
163
extra_duration
@@ -202,6 +204,20 @@ impl IntegrationTests {
202
204
println ! ( " Time: {rust_time:.2}s." ) ;
203
205
}
204
206
207
+ if !all_passed {
208
+ println ! ( "\n Failed tests:" ) ;
209
+ let max = 10 ;
210
+ for test in self . failed_list . iter ( ) . take ( max) {
211
+ println ! ( " * {test}" ) ;
212
+ }
213
+
214
+ if self . failed_list . len ( ) > max {
215
+ println ! ( " * ... and {} more." , self . failed_list. len( ) - max) ;
216
+ }
217
+
218
+ println ! ( ) ;
219
+ }
220
+
205
221
if focused_run && !allow_focus {
206
222
println ! ( " {FMT_YELLOW}Focus run disallowed; return failure.{FMT_END}" ) ;
207
223
false
@@ -229,11 +245,15 @@ impl IntegrationTests {
229
245
230
246
fn conclude_benchmarks ( & self ) { }
231
247
232
- fn update_stats ( & mut self , outcome : & TestOutcome ) {
248
+ fn update_stats ( & mut self , outcome : & TestOutcome , test_file : & str , test_name : & str ) {
233
249
self . total += 1 ;
234
250
match outcome {
235
251
TestOutcome :: Passed => self . passed += 1 ,
236
- TestOutcome :: Failed => { }
252
+ TestOutcome :: Failed => self . failed_list . push ( format ! (
253
+ "{} > {}" ,
254
+ extract_file_subtitle( test_file) ,
255
+ test_name
256
+ ) ) ,
237
257
TestOutcome :: Skipped => self . skipped += 1 ,
238
258
}
239
259
}
@@ -281,19 +301,21 @@ fn print_file_header(file: String, last_file: &mut Option<String>) {
281
301
. map_or ( true , |last_file| last_file != & file) ;
282
302
283
303
if print_file {
284
- let file_subtitle = if let Some ( sep_pos) = file. rfind ( & [ '/' , '\\' ] ) {
285
- & file[ sep_pos + 1 ..]
286
- } else {
287
- file. as_str ( )
288
- } ;
289
-
290
- println ! ( "\n {file_subtitle}:" ) ;
304
+ println ! ( "\n {}:" , extract_file_subtitle( & file) ) ;
291
305
}
292
306
293
307
// State update for file-category-print
294
308
* last_file = Some ( file) ;
295
309
}
296
310
311
+ fn extract_file_subtitle ( file : & str ) -> & str {
312
+ if let Some ( sep_pos) = file. rfind ( & [ '/' , '\\' ] ) {
313
+ & file[ sep_pos + 1 ..]
314
+ } else {
315
+ file
316
+ }
317
+ }
318
+
297
319
/// Prints a test name and its outcome.
298
320
///
299
321
/// Note that this is run after a test run, so stdout/stderr output during the test will be printed before.
0 commit comments