@@ -286,6 +286,9 @@ pub struct TestOpts {
286286 pub logfile : Option < Path > ,
287287 pub nocapture : bool ,
288288 pub color : ColorConfig ,
289+ pub show_boxplot : bool ,
290+ pub boxplot_width : uint ,
291+ pub show_all_stats : bool ,
289292}
290293
291294impl TestOpts {
@@ -303,6 +306,9 @@ impl TestOpts {
303306 logfile : None ,
304307 nocapture : false ,
305308 color : AutoColor ,
309+ show_boxplot : false ,
310+ boxplot_width : 50 ,
311+ show_all_stats : false ,
306312 }
307313 }
308314}
@@ -333,7 +339,10 @@ fn optgroups() -> Vec<getopts::OptGroup> {
333339 getopts:: optopt( "" , "color" , "Configure coloring of output:
334340 auto = colorize if stdout is a tty and tests are run on serially (default);
335341 always = always colorize output;
336- never = never colorize output;" , "auto|always|never" ) )
342+ never = never colorize output;" , "auto|always|never" ) ,
343+ getopts:: optflag( "" , "boxplot" , "Display a boxplot of the benchmark statistics" ) ,
344+ getopts:: optopt( "" , "boxplot-width" , "Set the boxplot width (default 50)" , "WIDTH" ) ,
345+ getopts:: optflag( "" , "stats" , "Display the benchmark min, max, and quartiles" ) )
337346}
338347
339348fn usage ( binary : & str ) {
@@ -424,6 +433,21 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
424433 v) ) ) ,
425434 } ;
426435
436+ let show_boxplot = matches. opt_present ( "boxplot" ) ;
437+ let boxplot_width = match matches. opt_str ( "boxplot-width" ) {
438+ Some ( width) => {
439+ match FromStr :: from_str ( width. as_slice ( ) ) {
440+ Some ( width) => width,
441+ None => {
442+ return Some ( Err ( format ! ( "argument for --boxplot-width must be a uint" ) ) ) ;
443+ }
444+ }
445+ }
446+ None => 50 ,
447+ } ;
448+
449+ let show_all_stats = matches. opt_present ( "stats" ) ;
450+
427451 let test_opts = TestOpts {
428452 filter : filter,
429453 run_ignored : run_ignored,
@@ -436,6 +460,9 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
436460 logfile : logfile,
437461 nocapture : nocapture,
438462 color : color,
463+ show_boxplot : show_boxplot,
464+ boxplot_width : boxplot_width,
465+ show_all_stats : show_all_stats,
439466 } ;
440467
441468 Some ( Ok ( test_opts) )
@@ -486,6 +513,9 @@ struct ConsoleTestState<T> {
486513 log_out : Option < File > ,
487514 out : OutputLocation < T > ,
488515 use_color : bool ,
516+ show_boxplot : bool ,
517+ boxplot_width : uint ,
518+ show_all_stats : bool ,
489519 total : uint ,
490520 passed : uint ,
491521 failed : uint ,
@@ -512,6 +542,9 @@ impl<T: Writer> ConsoleTestState<T> {
512542 out : out,
513543 log_out : log_out,
514544 use_color : use_color ( opts) ,
545+ show_boxplot : opts. show_boxplot ,
546+ boxplot_width : opts. boxplot_width ,
547+ show_all_stats : opts. show_all_stats ,
515548 total : 0 u,
516549 passed : 0 u,
517550 failed : 0 u,
@@ -607,8 +640,31 @@ impl<T: Writer> ConsoleTestState<T> {
607640 }
608641 TrBench ( ref bs) => {
609642 try!( self . write_bench ( ) ) ;
610- self . write_plain ( format ! ( ": {}" ,
611- fmt_bench_samples( bs) ) . as_slice ( ) )
643+
644+ if self . show_boxplot {
645+ let mut wr = Vec :: new ( ) ;
646+
647+ try!( stats:: write_boxplot ( & mut wr, & bs. ns_iter_summ , self . boxplot_width ) ) ;
648+
649+ let s = String :: from_utf8 ( wr) . unwrap ( ) ;
650+
651+ try!( self . write_plain ( format ! ( ": {}" , s) . as_slice ( ) ) ) ;
652+ }
653+
654+ if self . show_all_stats {
655+ let mut wr = Vec :: new ( ) ;
656+
657+ try!( stats:: write_5_number_summary ( & mut wr, & bs. ns_iter_summ ) ) ;
658+
659+ let s = String :: from_utf8 ( wr) . unwrap ( ) ;
660+
661+ try!( self . write_plain ( format ! ( ": {}" , s) . as_slice ( ) ) ) ;
662+ } else {
663+ try!( self . write_plain ( format ! ( ": {}" ,
664+ fmt_bench_samples( bs) ) . as_slice ( ) ) ) ;
665+ }
666+
667+ Ok ( ( ) )
612668 }
613669 } ) ;
614670 self . write_plain ( "\n " )
@@ -681,14 +737,14 @@ impl<T: Writer> ConsoleTestState<T> {
681737 }
682738 Improvement ( pct) => {
683739 improved += 1 ;
684- try!( self . write_plain ( format ! ( ": {}" , * k) . as_slice ( ) ) ) ;
740+ try!( self . write_plain ( format ! ( ": {} " , * k) . as_slice ( ) ) ) ;
685741 try!( self . write_improved ( ) ) ;
686742 try!( self . write_plain ( format ! ( " by {:.2}%\n " ,
687743 pct as f64 ) . as_slice ( ) ) ) ;
688744 }
689745 Regression ( pct) => {
690746 regressed += 1 ;
691- try!( self . write_plain ( format ! ( ": {}" , * k) . as_slice ( ) ) ) ;
747+ try!( self . write_plain ( format ! ( ": {} " , * k) . as_slice ( ) ) ) ;
692748 try!( self . write_regressed ( ) ) ;
693749 try!( self . write_plain ( format ! ( " by {:.2}%\n " ,
694750 pct as f64 ) . as_slice ( ) ) ) ;
@@ -860,6 +916,9 @@ fn should_sort_failures_before_printing_them() {
860916 log_out : None ,
861917 out : Raw ( Vec :: new ( ) ) ,
862918 use_color : false ,
919+ show_boxplot : false ,
920+ boxplot_width : 0 ,
921+ show_all_stats : false ,
863922 total : 0 u,
864923 passed : 0 u,
865924 failed : 0 u,
0 commit comments