@@ -54,92 +54,141 @@ pub trait Reporter<TData = ()>: Send + Sync {
5454pub struct LogReporter ;
5555
5656impl LogReporter {
57- pub fn build_end_test_message (
57+ pub fn write_report_category_start < TData , W : std:: io:: Write > (
58+ writer : & mut W ,
59+ category : & CollectedTestCategory < TData > ,
60+ ) -> std:: io:: Result < ( ) > {
61+ writeln ! ( writer) ?;
62+ writeln ! (
63+ writer,
64+ " {} {}" ,
65+ colors:: green_bold( "Running" ) ,
66+ category. name
67+ ) ?;
68+ writeln ! ( writer) ?;
69+ Ok ( ( ) )
70+ }
71+
72+ pub fn write_report_test_start < TData , W : std:: io:: Write > (
73+ writer : & mut W ,
74+ test : & CollectedTest < TData > ,
75+ context : & ReporterContext ,
76+ ) -> std:: io:: Result < ( ) > {
77+ if !context. is_parallel {
78+ if * NO_CAPTURE {
79+ writeln ! ( writer, "test {} ..." , test. name) ?;
80+ } else {
81+ write ! ( writer, "test {} ... " , test. name) ?;
82+ }
83+ }
84+ Ok ( ( ) )
85+ }
86+
87+ pub fn write_report_test_end < TData , W : std:: io:: Write > (
88+ writer : & mut W ,
89+ test : & CollectedTest < TData > ,
90+ duration : Duration ,
91+ result : & TestResult ,
92+ context : & ReporterContext ,
93+ ) -> std:: io:: Result < ( ) > {
94+ if context. is_parallel {
95+ write ! ( writer, "test {} ... " , test. name) ?;
96+ }
97+ Self :: write_end_test_message ( writer, result, duration) ?;
98+ Ok ( ( ) )
99+ }
100+
101+ pub fn write_end_test_message < W : std:: io:: Write > (
102+ writer : & mut W ,
58103 result : & TestResult ,
59104 duration : Duration ,
60- ) -> String {
61- fn output_sub_tests (
105+ ) -> std:: io:: Result < ( ) > {
106+ fn output_sub_tests < W : std:: io:: Write > (
107+ writer : & mut W ,
62108 indent : & str ,
63109 sub_tests : & [ SubTestResult ] ,
64- runner_output : & mut String ,
65- ) {
110+ ) -> std:: io:: Result < ( ) > {
66111 for sub_test in sub_tests {
67112 match & sub_test. result {
68113 TestResult :: Passed => {
69- runner_output. push_str ( & format ! (
70- "{}{} {}\n " ,
114+ writeln ! (
115+ writer,
116+ "{}{} {}" ,
71117 indent,
72118 sub_test. name,
73119 colors:: green_bold( "ok" ) ,
74- ) ) ;
120+ ) ? ;
75121 }
76122 TestResult :: Ignored => {
77- runner_output. push_str ( & format ! (
78- "{}{} {}\n " ,
123+ writeln ! (
124+ writer,
125+ "{}{} {}" ,
79126 indent,
80127 sub_test. name,
81128 colors:: gray( "ignored" ) ,
82- ) ) ;
129+ ) ? ;
83130 }
84131 TestResult :: Failed { .. } => {
85- runner_output. push_str ( & format ! (
86- "{}{} {}\n " ,
132+ writeln ! (
133+ writer,
134+ "{}{} {}" ,
87135 indent,
88136 sub_test. name,
89137 colors:: red_bold( "fail" )
90- ) ) ;
138+ ) ? ;
91139 }
92140 TestResult :: SubTests ( sub_tests) => {
93- runner_output . push_str ( & format ! ( "{}{}\n " , indent, sub_test. name) ) ;
141+ writeln ! ( writer , "{}{}" , indent, sub_test. name) ? ;
94142 if sub_tests. is_empty ( ) {
95- runner_output. push_str ( & format ! (
96- "{} {}\n " ,
143+ writeln ! (
144+ writer,
145+ "{} {}" ,
97146 indent,
98147 colors:: gray( "<no sub-tests>" )
99- ) ) ;
148+ ) ? ;
100149 } else {
101- output_sub_tests (
102- & format ! ( "{} " , indent) ,
103- sub_tests,
104- runner_output,
105- ) ;
150+ output_sub_tests ( writer, & format ! ( "{} " , indent) , sub_tests) ?;
106151 }
107152 }
108153 }
109154 }
155+ Ok ( ( ) )
110156 }
111157
112- let mut runner_output = String :: new ( ) ;
113158 let duration_display =
114159 colors:: gray ( format ! ( "({}ms)" , duration. as_millis( ) ) ) ;
115160 match result {
116161 TestResult :: Passed => {
117- runner_output. push_str ( & format ! (
118- "{} {}\n " ,
119- colors:: green_bold( "ok" ) ,
120- duration_display
121- ) ) ;
162+ writeln ! ( writer, "{} {}" , colors:: green_bold( "ok" ) , duration_display) ?;
122163 }
123164 TestResult :: Ignored => {
124- runner_output . push_str ( & format ! ( "{}\n " , colors:: gray( "ignored" ) ) ) ;
165+ writeln ! ( writer , "{}" , colors:: gray( "ignored" ) ) ? ;
125166 }
126167 TestResult :: Failed { .. } => {
127- runner_output. push_str ( & format ! (
128- "{} {}\n " ,
129- colors:: red_bold( "fail" ) ,
130- duration_display
131- ) ) ;
168+ writeln ! ( writer, "{} {}" , colors:: red_bold( "fail" ) , duration_display) ?;
132169 }
133170 TestResult :: SubTests ( sub_tests) => {
134- runner_output . push_str ( & format ! ( "{}\n " , duration_display) ) ;
135- output_sub_tests ( " " , sub_tests, & mut runner_output ) ;
171+ writeln ! ( writer , "{}" , duration_display) ? ;
172+ output_sub_tests ( writer , " " , sub_tests) ? ;
136173 }
137174 }
138175
139- runner_output
176+ Ok ( ( ) )
177+ }
178+
179+ pub fn write_report_long_running_test < W : std:: io:: Write > (
180+ writer : & mut W ,
181+ test_name : & str ,
182+ ) -> std:: io:: Result < ( ) > {
183+ writeln ! (
184+ writer,
185+ "test {} has been running for more than 60 seconds" ,
186+ test_name
187+ ) ?;
188+ Ok ( ( ) )
140189 }
141190
142- pub fn write_failures < TData , W : std:: io:: Write > (
191+ pub fn write_report_failures < TData , W : std:: io:: Write > (
143192 writer : & mut W ,
144193 failures : & [ ReporterFailure < TData > ] ,
145194 total_tests : usize ,
@@ -182,9 +231,10 @@ impl<TData> Reporter<TData> for LogReporter {
182231 category : & CollectedTestCategory < TData > ,
183232 _context : & ReporterContext ,
184233 ) {
185- eprintln ! ( ) ;
186- eprintln ! ( " {} {}" , colors:: green_bold( "Running" ) , category. name) ;
187- eprintln ! ( ) ;
234+ let _ = LogReporter :: write_report_category_start (
235+ & mut std:: io:: stderr ( ) ,
236+ category,
237+ ) ;
188238 }
189239
190240 fn report_category_end (
@@ -199,13 +249,11 @@ impl<TData> Reporter<TData> for LogReporter {
199249 test : & CollectedTest < TData > ,
200250 context : & ReporterContext ,
201251 ) {
202- if !context. is_parallel {
203- if * NO_CAPTURE {
204- eprintln ! ( "test {} ..." , test. name) ;
205- } else {
206- eprint ! ( "test {} ... " , test. name) ;
207- }
208- }
252+ let _ = LogReporter :: write_report_test_start (
253+ & mut std:: io:: stderr ( ) ,
254+ test,
255+ context,
256+ ) ;
209257 }
210258
211259 fn report_test_end (
@@ -215,18 +263,19 @@ impl<TData> Reporter<TData> for LogReporter {
215263 result : & TestResult ,
216264 context : & ReporterContext ,
217265 ) {
218- let runner_output = LogReporter :: build_end_test_message ( result, duration) ;
219- if context. is_parallel {
220- eprint ! ( "test {} ... {}" , test. name, runner_output) ;
221- } else {
222- eprint ! ( "{}" , runner_output) ;
223- }
266+ let _ = LogReporter :: write_report_test_end (
267+ & mut std:: io:: stderr ( ) ,
268+ test,
269+ duration,
270+ result,
271+ context,
272+ ) ;
224273 }
225274
226275 fn report_long_running_test ( & self , test_name : & str ) {
227- eprintln ! (
228- "test {} has been running for more than 60 seconds" ,
229- test_name
276+ let _ = LogReporter :: write_report_long_running_test (
277+ & mut std :: io :: stderr ( ) ,
278+ test_name,
230279 ) ;
231280 }
232281
@@ -235,7 +284,7 @@ impl<TData> Reporter<TData> for LogReporter {
235284 failures : & [ ReporterFailure < TData > ] ,
236285 total_tests : usize ,
237286 ) {
238- let _ = LogReporter :: write_failures (
287+ let _ = LogReporter :: write_report_failures (
239288 & mut std:: io:: stderr ( ) ,
240289 failures,
241290 total_tests,
@@ -249,10 +298,19 @@ mod test {
249298
250299 use super :: * ;
251300
301+ fn build_end_test_message (
302+ result : & TestResult ,
303+ duration : std:: time:: Duration ,
304+ ) -> String {
305+ let mut output = Vec :: new ( ) ;
306+ LogReporter :: write_end_test_message ( & mut output, result, duration) . unwrap ( ) ;
307+ String :: from_utf8 ( output) . unwrap ( )
308+ }
309+
252310 #[ test]
253311 fn test_build_end_test_message_passed ( ) {
254312 assert_eq ! (
255- LogReporter :: build_end_test_message(
313+ build_end_test_message(
256314 & super :: TestResult :: Passed ,
257315 std:: time:: Duration :: from_millis( 100 ) ,
258316 ) ,
@@ -262,7 +320,7 @@ mod test {
262320
263321 #[ test]
264322 fn test_build_end_test_message_failed ( ) {
265- let message = LogReporter :: build_end_test_message (
323+ let message = build_end_test_message (
266324 & super :: TestResult :: Failed {
267325 output : b"error" . to_vec ( ) ,
268326 } ,
@@ -277,7 +335,7 @@ mod test {
277335 #[ test]
278336 fn test_build_end_test_message_ignored ( ) {
279337 assert_eq ! (
280- LogReporter :: build_end_test_message(
338+ build_end_test_message(
281339 & super :: TestResult :: Ignored ,
282340 std:: time:: Duration :: from_millis( 10 ) ,
283341 ) ,
@@ -287,7 +345,7 @@ mod test {
287345
288346 #[ test]
289347 fn test_build_end_test_message_sub_tests ( ) {
290- let message = LogReporter :: build_end_test_message (
348+ let message = build_end_test_message (
291349 & super :: TestResult :: SubTests ( vec ! [
292350 super :: SubTestResult {
293351 name: "step1" . to_string( ) ,
0 commit comments