class Minitest::Reporters::MeanTimeReporter


rake reset_statistics
a simple rake task:
(configurable) report. These statistics can be reset at any time by using
file which is parsed at the end of each run to provide a new
This is achieved by creating a (configurable) ‘previous runs’ statistics
3) Provide an abundance of statistics to enjoy.
your tests or algorithms in your code.
2) Identify (and fix) regressions in test run speed caused by changes to
for improvements or refactoring.
1) Identify the slowest running tests over time as potential candidates
allow you to:
maximum times for a test to run. Running this for all your tests will
This reporter creates a report providing the average (mean), minimum and

def self.reset_statistics!

Returns:
  • (Boolean) -
def self.reset_statistics!
  new.reset_statistics!
end

def after_suite(suite)

Returns:
  • (Hash Float>) -
def after_suite(suite)
  super
  @all_suite_times = @suite_times
end

def asc?

Returns:
  • (Boolean) - Whether the given :order option is :asc.
def asc?
  order == :asc
end

def avg_label

Returns:
  • (String) - A yellow 'Avg:' label.
def avg_label
  ANSI::Code.yellow('Avg:')
end

def column_sorted_body

Returns:
  • (Array String>>) - All of the results sorted by
def column_sorted_body
  runs = options[:show_all_runs] ? previous_run : current_run
  runs.keys.each_with_object([]) do |description, obj|
    timings = previous_run[description]
    size = Array(timings).size
    sum  = Array(timings).inject { |total, x| total + x }
    obj << {
      avg:  (sum / size).round(9),
      min:  Array(timings).min.round(9),
      max:  Array(timings).max.round(9),
      last: Array(timings).last.round(9),
      desc: description,
    }
  end.sort_by { |k| k[sort_column] }
end

def create_new_report!

Returns:
  • (void) -
def create_new_report!
  File.write(report_filename, report_title + report_body)
end

def create_or_update_previous_runs!

Returns:
  • (void) -
def create_or_update_previous_runs!
  if previously_ran?
    current_run.each do |description, elapsed|
    new_times = if previous_run["#{description}"]
                  Array(previous_run["#{description}"]) << elapsed
                else
                  Array(elapsed)
                end
      previous_run.store("#{description}", new_times)
    end
    File.write(previous_runs_filename, previous_run.to_yaml)
  else
    File.write(previous_runs_filename, current_run.to_yaml)
  end
end

def current_run

Returns:
  • (Hash Float>) -
def current_run
  Hash[all_suite_times]
end

def defaults

Returns:
  • (Hash) - Sets default values for the filenames used by this class,
def defaults
  {
    order:                  :desc,
    show_count:             15,
    show_progress:          true,
    show_all_runs:          true,
    sort_column:            :avg,
    previous_runs_filename: '/tmp/minitest_reporters_previous_run',
    report_filename:        '/tmp/minitest_reporters_report',
  }
end

def des_label

Returns:
  • (String) - A blue 'Description:' label.
def des_label
  ANSI::Code.blue('Description:')
end

def desc?

Returns:
  • (Boolean) - Whether the given :order option is :desc (default).
def desc?
  order == :desc
end

def initialize(options = {})

Returns:
  • (Minitest::Reporters::MeanTimeReporter) -

Options Hash: (**order)
  • One (Symbol) -- of :desc (default), or :asc. By default the
  • One (Symbol) -- of :avg (default), :min, :max, :last.
  • If (Boolean) -- true it shows all recorded suit results.
  • If (Boolean) -- true it prints pass/skip/fail marks.
  • The (Fixnum) -- number of tests to show in the report
  • Contains (String) -- the parsed results for the
  • Contains (String) -- the times for each test

Parameters:
  • options (Hash) --
def initialize(options = {})
  super
  @all_suite_times = []
end

def max_label

Returns:
  • (String) - A red 'Max:' label.
def max_label
  ANSI::Code.red('Max:')
end

def min_label

Returns:
  • (String) - A green 'Min:' label.
def min_label
  ANSI::Code.green('Min:')
end

def on_record(test)

def on_record(test)
  super if options[:show_progress]
end

def on_report

def on_report
  super if options[:show_progress]
end

def on_start

def on_start
  super if options[:show_progress]
end

def options

Returns:
  • (Hash) -
def options
  defaults.merge!(@options)
end

def order

Returns:
  • (Symbol) - The :order option, or by default; :desc.

Raises:
  • (Minitest::Reporters::MeanTimeReporter::InvalidOrder) -
def order
  orders = [:desc, :asc]
  if orders.include?(options[:order])
    options[:order]
  else
    fail Minitest::Reporters::MeanTimeReporter::InvalidOrder,
         "`:order` option must be one of #{orders.inspect}."
  end
end

def order_sorted_body

Returns:
  • (String) - All of the column-sorted results sorted by the :order
def order_sorted_body
  if desc?
    column_sorted_body.reverse
  elsif asc?
    column_sorted_body
  end
end

def previous_run

Returns:
  • (Hash Array]) - Hash Array]
def previous_run
  @previous_run ||= YAML.load_file(previous_runs_filename)
end

def previous_runs_filename

Returns:
  • (String) - The path to the file which contains all the durations
def previous_runs_filename
  options[:previous_runs_filename]
end

def previously_ran?

Returns:
  • (Boolean) -
def previously_ran?
  File.exist?(previous_runs_filename)
end

def rate(run, min, max)

Returns:
  • (Symbol) - One of :faster, :slower or :inconclusive.

Parameters:
  • max (Float) -- The maximum run time.
  • min (Float) -- The minimum run time.
  • run (Float) -- The last run time.
def rate(run, min, max)
  if run == min
    :faster
  elsif run == max
    :slower
  else
    :inconclusive
  end
end

def report


terminal.
outputs the parsed results to both the 'report_filename' and the
enhances it by storing the results to the 'previous_runs_filename' and
Runs the {Minitest::Reporters::DefaultReporter#report} method and then
def report
  super
  create_or_update_previous_runs!
  create_new_report!
  write_to_screen!
end

def report_body

Returns:
  • (String) -
def report_body
  order_sorted_body.each_with_object([]) do |result, obj|
    rating = rate(result[:last], result[:min], result[:max])
    obj << "#{avg_label} #{result[:avg].to_s.ljust(12)} " \
           "#{min_label} #{result[:min].to_s.ljust(12)} " \
           "#{max_label} #{result[:max].to_s.ljust(12)} " \
           "#{run_label(rating)} #{result[:last].to_s.ljust(12)} " \
           "#{des_label} #{result[:desc]}\n"
  end.join
end

def report_filename

Returns:
  • (String) - The path to the file which contains the parsed test
def report_filename
  options[:report_filename]
end

def report_title

Returns:
  • (String) -
def report_title
  "\n\e[4mMinitest Reporters: Mean Time Report\e[24m " \
  "(Samples: #{samples}, Order: #{sort_column.inspect} " \
  "#{order.inspect})\n"
end

def reset_statistics!

Returns:
  • (void) -
def reset_statistics!
  File.open(previous_runs_filename, 'w+') { |f| f.write('') }
end

def run_label(rating)

Returns:
  • (String) - A purple 'Last:' label.

Parameters:
  • rating (Symbol) -- One of :faster, :slower or :inconclusive.
def run_label(rating)
  case rating
  when :faster then ANSI::Code.green('Last:')
  when :slower then ANSI::Code.red('Last:')
  else
    ANSI::Code.magenta('Last:')
  end
end

def samples

Returns:
  • (Fixnum) -
def samples
  return 1 unless previous_run.first[1].is_a?(Array)
  previous_run.first[1].size
end

def show_count

Returns:
  • (Fixnum) - The number of tests to output to output to the screen
def show_count
  options[:show_count]
end

def sort_column

Returns:
  • (Symbol) - The :sort_column option, or by default; :avg.

Raises:
  • (Minitest::Reporters::MeanTimeReporter::InvalidSortColumn) -
def sort_column
  sort_columns = [:avg, :min, :max, :last]
  if sort_columns.include?(options[:sort_column])
    options[:sort_column]
  else
    fail Minitest::Reporters::MeanTimeReporter::InvalidSortColumn,
         "`:sort_column` option must be one of #{sort_columns.inspect}."
  end
end

def write_to_screen!

Returns:
  • (void) -
def write_to_screen!
  puts report_title
  puts report_body.lines.take(show_count)
end