minitest-reporters 1.3.0 → 1.3.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +27 -27
  3. data/.ruby-gemset +1 -1
  4. data/.travis.yml +10 -10
  5. data/.yardopts +5 -5
  6. data/CHANGELOG.md +58 -54
  7. data/Gemfile +2 -2
  8. data/LICENSE +19 -19
  9. data/README.md +134 -134
  10. data/Rakefile +60 -60
  11. data/lib/minitest/extensible_backtrace_filter.rb +67 -67
  12. data/lib/minitest/minitest_reporter_plugin.rb +75 -75
  13. data/lib/minitest/old_activesupport_fix.rb +24 -24
  14. data/lib/minitest/relative_position.rb +26 -26
  15. data/lib/minitest/reporters.rb +91 -91
  16. data/lib/minitest/reporters/ansi.rb +31 -31
  17. data/lib/minitest/reporters/base_reporter.rb +119 -117
  18. data/lib/minitest/reporters/default_reporter.rb +228 -228
  19. data/lib/minitest/reporters/html_reporter.rb +221 -221
  20. data/lib/minitest/reporters/junit_reporter.rb +158 -158
  21. data/lib/minitest/reporters/mean_time_reporter.rb +392 -392
  22. data/lib/minitest/reporters/progress_reporter.rb +96 -96
  23. data/lib/minitest/reporters/ruby_mate_reporter.rb +54 -54
  24. data/lib/minitest/reporters/rubymine_reporter.rb +117 -117
  25. data/lib/minitest/reporters/spec_reporter.rb +61 -61
  26. data/lib/minitest/reporters/version.rb +5 -5
  27. data/lib/minitest/templates/index.html.erb +82 -82
  28. data/minitest-reporters.gemspec +31 -31
  29. data/test/fixtures/junit_filename_bug_example_test.rb +21 -21
  30. data/test/fixtures/mean_time_test.rb +8 -8
  31. data/test/fixtures/progress_detailed_skip_test.rb +8 -8
  32. data/test/fixtures/progress_test.rb +8 -8
  33. data/test/fixtures/sample_test.rb +15 -15
  34. data/test/fixtures/spec_test.rb +13 -13
  35. data/test/gallery/bad_test.rb +25 -25
  36. data/test/gallery/good_test.rb +14 -14
  37. data/test/integration/reporters/junit_reporter_test.rb +12 -12
  38. data/test/integration/reporters/mean_time_reporter_test.rb +7 -7
  39. data/test/integration/reporters/progress_reporter_test.rb +34 -34
  40. data/test/test_helper.rb +22 -22
  41. data/test/unit/minitest/extensible_backtrace_filter_test.rb +42 -42
  42. data/test/unit/minitest/mean_time_reporter_unit_test.rb +152 -152
  43. data/test/unit/minitest/minitest_reporter_plugin_test.rb +14 -14
  44. data/test/unit/minitest/reporters_test.rb +65 -65
  45. data/test/unit/minitest/spec_reporter_test.rb +41 -41
  46. metadata +4 -4
@@ -1,392 +1,392 @@
1
- require 'minitest/reporters'
2
- require 'yaml'
3
-
4
- module Minitest
5
- module Reporters
6
-
7
- # This reporter creates a report providing the average (mean), minimum and
8
- # maximum times for a test to run. Running this for all your tests will
9
- # allow you to:
10
- #
11
- # 1) Identify the slowest running tests over time as potential candidates
12
- # for improvements or refactoring.
13
- # 2) Identify (and fix) regressions in test run speed caused by changes to
14
- # your tests or algorithms in your code.
15
- # 3) Provide an abundance of statistics to enjoy.
16
- #
17
- # This is achieved by creating a (configurable) 'previous runs' statistics
18
- # file which is parsed at the end of each run to provide a new
19
- # (configurable) report. These statistics can be reset at any time by using
20
- # a simple rake task:
21
- #
22
- # rake reset_statistics
23
- #
24
- class MeanTimeReporter < Minitest::Reporters::DefaultReporter
25
-
26
- class InvalidOrder < StandardError; end
27
- class InvalidSortColumn < StandardError; end
28
-
29
- # Reset the statistics file for this reporter. Called via a rake task:
30
- #
31
- # rake reset_statistics
32
- #
33
- # @return [Boolean]
34
- def self.reset_statistics!
35
- new.reset_statistics!
36
- end
37
-
38
- # @param options [Hash]
39
- # @option previous_runs_filename [String] Contains the times for each test
40
- # by description. Defaults to '/tmp/minitest_reporters_previous_run'.
41
- # @option report_filename [String] Contains the parsed results for the
42
- # last test run. Defaults to '/tmp/minitest_reporters_report'.
43
- # @option show_count [Fixnum] The number of tests to show in the report
44
- # summary at the end of the test run. Default is 15.
45
- # @option show_progress [Boolean] If true it prints pass/skip/fail marks.
46
- # Default is true.
47
- # @option show_all_runs [Boolean] If true it shows all recorded suit results.
48
- # Default is true.
49
- # @option sort_column [Symbol] One of :avg (default), :min, :max, :last.
50
- # Determines the column by which the report summary is sorted.
51
- # @option order [Symbol] One of :desc (default), or :asc. By default the
52
- # report summary is listed slowest to fastest (:desc). :asc will order
53
- # the report summary as fastest to slowest.
54
- # @return [Minitest::Reporters::MeanTimeReporter]
55
- def initialize(options = {})
56
- super
57
-
58
- @all_suite_times = []
59
- end
60
-
61
- # Copies the suite times from the
62
- # {Minitest::Reporters::DefaultReporter#after_suite} method, making them
63
- # available to this class.
64
- #
65
- # @return [Hash<String => Float>]
66
- def after_suite(suite)
67
- super
68
-
69
- @all_suite_times = @suite_times
70
- end
71
-
72
- # Runs the {Minitest::Reporters::DefaultReporter#report} method and then
73
- # enhances it by storing the results to the 'previous_runs_filename' and
74
- # outputs the parsed results to both the 'report_filename' and the
75
- # terminal.
76
- #
77
- def report
78
- super
79
-
80
- create_or_update_previous_runs!
81
-
82
- create_new_report!
83
-
84
- write_to_screen!
85
- end
86
-
87
- def on_start
88
- super if options[:show_progress]
89
- end
90
-
91
- def on_record(test)
92
- super if options[:show_progress]
93
- end
94
-
95
- def on_report
96
- super if options[:show_progress]
97
- end
98
-
99
- # Resets the 'previous runs' file, essentially removing all previous
100
- # statistics gathered.
101
- #
102
- # @return [void]
103
- def reset_statistics!
104
- File.open(previous_runs_filename, 'w+') { |f| f.write('') }
105
- end
106
-
107
- protected
108
-
109
- attr_accessor :all_suite_times
110
-
111
- private
112
-
113
- # @return [Hash<String => Float>]
114
- def current_run
115
- Hash[all_suite_times]
116
- end
117
-
118
- # @return [Hash] Sets default values for the filenames used by this class,
119
- # and the number of tests to output to output to the screen after each
120
- # run.
121
- def defaults
122
- {
123
- order: :desc,
124
- show_count: 15,
125
- show_progress: true,
126
- show_all_runs: true,
127
- sort_column: :avg,
128
- previous_runs_filename: '/tmp/minitest_reporters_previous_run',
129
- report_filename: '/tmp/minitest_reporters_report',
130
- }
131
- end
132
-
133
- # Added to the top of the report file and to the screen output.
134
- #
135
- # @return [String]
136
- def report_title
137
- "\n\e[4mMinitest Reporters: Mean Time Report\e[24m " \
138
- "(Samples: #{samples}, Order: #{sort_column.inspect} " \
139
- "#{order.inspect})\n"
140
- end
141
-
142
- # The report itself. Displays statistics about all runs, ideal for use
143
- # with the Unix 'head' command. Listed in slowest average descending
144
- # order.
145
- #
146
- # @return [String]
147
- def report_body
148
- order_sorted_body.each_with_object([]) do |result, obj|
149
- rating = rate(result[:last], result[:min], result[:max])
150
-
151
- obj << "#{avg_label} #{result[:avg].to_s.ljust(12)} " \
152
- "#{min_label} #{result[:min].to_s.ljust(12)} " \
153
- "#{max_label} #{result[:max].to_s.ljust(12)} " \
154
- "#{run_label(rating)} #{result[:last].to_s.ljust(12)} " \
155
- "#{des_label} #{result[:desc]}\n"
156
- end.join
157
- end
158
-
159
- # @return [String] All of the column-sorted results sorted by the :order
160
- # option. (Defaults to :desc).
161
- def order_sorted_body
162
- if desc?
163
- column_sorted_body.reverse
164
-
165
- elsif asc?
166
- column_sorted_body
167
-
168
- end
169
- end
170
-
171
- # @return [Array<Hash<Symbol => String>>] All of the results sorted by
172
- # the :sort_column option. (Defaults to :avg).
173
- def column_sorted_body
174
- runs = options[:show_all_runs] ? previous_run : current_run
175
- runs.keys.each_with_object([]) do |description, obj|
176
- timings = previous_run[description]
177
- size = Array(timings).size
178
- sum = Array(timings).inject { |total, x| total + x }
179
- obj << {
180
- avg: (sum / size).round(9),
181
- min: Array(timings).min.round(9),
182
- max: Array(timings).max.round(9),
183
- last: Array(timings).last.round(9),
184
- desc: description,
185
- }
186
- end.sort_by { |k| k[sort_column] }
187
- end
188
-
189
- # @return [Hash]
190
- def options
191
- defaults.merge!(@options)
192
- end
193
-
194
- # @return [Fixnum] The number of tests to output to output to the screen
195
- # after each run.
196
- def show_count
197
- options[:show_count]
198
- end
199
-
200
- # @return [Hash<String => Array<Float>]
201
- def previous_run
202
- @previous_run ||= YAML.load_file(previous_runs_filename)
203
- end
204
-
205
- # @return [String] The path to the file which contains all the durations
206
- # for each test run. The previous runs file is in YAML format, using the
207
- # test name for the key and an array containing the time taken to run
208
- # this test for values.
209
- def previous_runs_filename
210
- options[:previous_runs_filename]
211
- end
212
-
213
- # Returns a boolean indicating whether a previous runs file exists.
214
- #
215
- # @return [Boolean]
216
- def previously_ran?
217
- File.exist?(previous_runs_filename)
218
- end
219
-
220
- # @return [String] The path to the file which contains the parsed test
221
- # results. The results file contains a line for each test with the
222
- # average time of the test, the minimum time the test took to run,
223
- # the maximum time the test took to run and a description of the test
224
- # (which is the test name as emitted by Minitest).
225
- def report_filename
226
- options[:report_filename]
227
- end
228
-
229
- # A barbaric way to find out how many runs are in the previous runs file;
230
- # this method takes the first test listed, and counts its samples
231
- # trusting (naively) all runs to be the same number of samples. This will
232
- # produce incorrect averages when new tests are added, so it is advised
233
- # to restart the statistics by removing the 'previous runs' file. A rake
234
- # task is provided to make this more convenient.
235
- #
236
- # rake reset_statistics
237
- #
238
- # @return [Fixnum]
239
- def samples
240
- return 1 unless previous_run.first[1].is_a?(Array)
241
-
242
- previous_run.first[1].size
243
- end
244
-
245
- # Creates a new 'previous runs' file, or updates the existing one with
246
- # the latest timings.
247
- #
248
- # @return [void]
249
- def create_or_update_previous_runs!
250
- if previously_ran?
251
- current_run.each do |description, elapsed|
252
- new_times = if previous_run["#{description}"]
253
- Array(previous_run["#{description}"]) << elapsed
254
-
255
- else
256
- Array(elapsed)
257
-
258
- end
259
-
260
- previous_run.store("#{description}", new_times)
261
- end
262
-
263
- File.write(previous_runs_filename, previous_run.to_yaml)
264
-
265
- else
266
-
267
- File.write(previous_runs_filename, current_run.to_yaml)
268
-
269
- end
270
- end
271
-
272
- # Creates a new report file in the 'report_filename'. This file contains
273
- # a line for each test of the following example format: (this is a single
274
- # line despite explicit wrapping)
275
- #
276
- # Avg: 0.0555555 Min: 0.0498765 Max: 0.0612345 Last: 0.0499421
277
- # Description: The test name
278
- #
279
- # Note however the timings are to 9 decimal places, and padded to 12
280
- # characters and each label is coloured, Avg (yellow), Min (green),
281
- # Max (red), Last (multi), and Description (blue). It looks pretty!
282
- #
283
- # The 'Last' label is special in that it will be colour coded depending
284
- # on whether the last run was faster (bright green) or slower (bright red)
285
- # or inconclusive (purple). This helps to identify changes on a per run
286
- # basis.
287
- #
288
- # @return [void]
289
- def create_new_report!
290
- File.write(report_filename, report_title + report_body)
291
- end
292
-
293
- # Writes a number of tests (configured via the 'show_count' option) to the
294
- # screen after creating the report. See '#create_new_report!' for example
295
- # output information.
296
- #
297
- # @return [void]
298
- def write_to_screen!
299
- puts report_title
300
- puts report_body.lines.take(show_count)
301
- end
302
-
303
- # @return [String] A yellow 'Avg:' label.
304
- def avg_label
305
- ANSI::Code.yellow('Avg:')
306
- end
307
-
308
- # @return [String] A blue 'Description:' label.
309
- def des_label
310
- ANSI::Code.blue('Description:')
311
- end
312
-
313
- # @return [String] A red 'Max:' label.
314
- def max_label
315
- ANSI::Code.red('Max:')
316
- end
317
-
318
- # @return [String] A green 'Min:' label.
319
- def min_label
320
- ANSI::Code.green('Min:')
321
- end
322
-
323
- # @param rating [Symbol] One of :faster, :slower or :inconclusive.
324
- # @return [String] A purple 'Last:' label.
325
- def run_label(rating)
326
- case rating
327
- when :faster then ANSI::Code.green('Last:')
328
- when :slower then ANSI::Code.red('Last:')
329
- else
330
- ANSI::Code.magenta('Last:')
331
- end
332
- end
333
-
334
- # @param run [Float] The last run time.
335
- # @param min [Float] The minimum run time.
336
- # @param max [Float] The maximum run time.
337
- # @return [Symbol] One of :faster, :slower or :inconclusive.
338
- def rate(run, min, max)
339
- if run == min
340
- :faster
341
- elsif run == max
342
- :slower
343
- else
344
- :inconclusive
345
- end
346
- end
347
-
348
- # @return [Boolean] Whether the given :order option is :asc.
349
- def asc?
350
- order == :asc
351
- end
352
-
353
- # @return [Boolean] Whether the given :order option is :desc (default).
354
- def desc?
355
- order == :desc
356
- end
357
-
358
- # @raise [Minitest::Reporters::MeanTimeReporter::InvalidOrder]
359
- # When the given :order option is invalid.
360
- # @return [Symbol] The :order option, or by default; :desc.
361
- def order
362
- orders = [:desc, :asc]
363
-
364
- if orders.include?(options[:order])
365
- options[:order]
366
-
367
- else
368
- fail Minitest::Reporters::MeanTimeReporter::InvalidOrder,
369
- "`:order` option must be one of #{orders.inspect}."
370
-
371
- end
372
- end
373
-
374
- # @raise [Minitest::Reporters::MeanTimeReporter::InvalidSortColumn]
375
- # When the given :sort_column option is invalid.
376
- # @return [Symbol] The :sort_column option, or by default; :avg.
377
- def sort_column
378
- sort_columns = [:avg, :min, :max, :last]
379
-
380
- if sort_columns.include?(options[:sort_column])
381
- options[:sort_column]
382
-
383
- else
384
- fail Minitest::Reporters::MeanTimeReporter::InvalidSortColumn,
385
- "`:sort_column` option must be one of #{sort_columns.inspect}."
386
-
387
- end
388
- end
389
-
390
- end
391
- end
392
- end
1
+ require 'minitest/reporters'
2
+ require 'yaml'
3
+
4
+ module Minitest
5
+ module Reporters
6
+
7
+ # This reporter creates a report providing the average (mean), minimum and
8
+ # maximum times for a test to run. Running this for all your tests will
9
+ # allow you to:
10
+ #
11
+ # 1) Identify the slowest running tests over time as potential candidates
12
+ # for improvements or refactoring.
13
+ # 2) Identify (and fix) regressions in test run speed caused by changes to
14
+ # your tests or algorithms in your code.
15
+ # 3) Provide an abundance of statistics to enjoy.
16
+ #
17
+ # This is achieved by creating a (configurable) 'previous runs' statistics
18
+ # file which is parsed at the end of each run to provide a new
19
+ # (configurable) report. These statistics can be reset at any time by using
20
+ # a simple rake task:
21
+ #
22
+ # rake reset_statistics
23
+ #
24
+ class MeanTimeReporter < Minitest::Reporters::DefaultReporter
25
+
26
+ class InvalidOrder < StandardError; end
27
+ class InvalidSortColumn < StandardError; end
28
+
29
+ # Reset the statistics file for this reporter. Called via a rake task:
30
+ #
31
+ # rake reset_statistics
32
+ #
33
+ # @return [Boolean]
34
+ def self.reset_statistics!
35
+ new.reset_statistics!
36
+ end
37
+
38
+ # @param options [Hash]
39
+ # @option previous_runs_filename [String] Contains the times for each test
40
+ # by description. Defaults to '/tmp/minitest_reporters_previous_run'.
41
+ # @option report_filename [String] Contains the parsed results for the
42
+ # last test run. Defaults to '/tmp/minitest_reporters_report'.
43
+ # @option show_count [Fixnum] The number of tests to show in the report
44
+ # summary at the end of the test run. Default is 15.
45
+ # @option show_progress [Boolean] If true it prints pass/skip/fail marks.
46
+ # Default is true.
47
+ # @option show_all_runs [Boolean] If true it shows all recorded suit results.
48
+ # Default is true.
49
+ # @option sort_column [Symbol] One of :avg (default), :min, :max, :last.
50
+ # Determines the column by which the report summary is sorted.
51
+ # @option order [Symbol] One of :desc (default), or :asc. By default the
52
+ # report summary is listed slowest to fastest (:desc). :asc will order
53
+ # the report summary as fastest to slowest.
54
+ # @return [Minitest::Reporters::MeanTimeReporter]
55
+ def initialize(options = {})
56
+ super
57
+
58
+ @all_suite_times = []
59
+ end
60
+
61
+ # Copies the suite times from the
62
+ # {Minitest::Reporters::DefaultReporter#after_suite} method, making them
63
+ # available to this class.
64
+ #
65
+ # @return [Hash<String => Float>]
66
+ def after_suite(suite)
67
+ super
68
+
69
+ @all_suite_times = @suite_times
70
+ end
71
+
72
+ # Runs the {Minitest::Reporters::DefaultReporter#report} method and then
73
+ # enhances it by storing the results to the 'previous_runs_filename' and
74
+ # outputs the parsed results to both the 'report_filename' and the
75
+ # terminal.
76
+ #
77
+ def report
78
+ super
79
+
80
+ create_or_update_previous_runs!
81
+
82
+ create_new_report!
83
+
84
+ write_to_screen!
85
+ end
86
+
87
+ def on_start
88
+ super if options[:show_progress]
89
+ end
90
+
91
+ def on_record(test)
92
+ super if options[:show_progress]
93
+ end
94
+
95
+ def on_report
96
+ super if options[:show_progress]
97
+ end
98
+
99
+ # Resets the 'previous runs' file, essentially removing all previous
100
+ # statistics gathered.
101
+ #
102
+ # @return [void]
103
+ def reset_statistics!
104
+ File.open(previous_runs_filename, 'w+') { |f| f.write('') }
105
+ end
106
+
107
+ protected
108
+
109
+ attr_accessor :all_suite_times
110
+
111
+ private
112
+
113
+ # @return [Hash<String => Float>]
114
+ def current_run
115
+ Hash[all_suite_times]
116
+ end
117
+
118
+ # @return [Hash] Sets default values for the filenames used by this class,
119
+ # and the number of tests to output to output to the screen after each
120
+ # run.
121
+ def defaults
122
+ {
123
+ order: :desc,
124
+ show_count: 15,
125
+ show_progress: true,
126
+ show_all_runs: true,
127
+ sort_column: :avg,
128
+ previous_runs_filename: '/tmp/minitest_reporters_previous_run',
129
+ report_filename: '/tmp/minitest_reporters_report',
130
+ }
131
+ end
132
+
133
+ # Added to the top of the report file and to the screen output.
134
+ #
135
+ # @return [String]
136
+ def report_title
137
+ "\n\e[4mMinitest Reporters: Mean Time Report\e[24m " \
138
+ "(Samples: #{samples}, Order: #{sort_column.inspect} " \
139
+ "#{order.inspect})\n"
140
+ end
141
+
142
+ # The report itself. Displays statistics about all runs, ideal for use
143
+ # with the Unix 'head' command. Listed in slowest average descending
144
+ # order.
145
+ #
146
+ # @return [String]
147
+ def report_body
148
+ order_sorted_body.each_with_object([]) do |result, obj|
149
+ rating = rate(result[:last], result[:min], result[:max])
150
+
151
+ obj << "#{avg_label} #{result[:avg].to_s.ljust(12)} " \
152
+ "#{min_label} #{result[:min].to_s.ljust(12)} " \
153
+ "#{max_label} #{result[:max].to_s.ljust(12)} " \
154
+ "#{run_label(rating)} #{result[:last].to_s.ljust(12)} " \
155
+ "#{des_label} #{result[:desc]}\n"
156
+ end.join
157
+ end
158
+
159
+ # @return [String] All of the column-sorted results sorted by the :order
160
+ # option. (Defaults to :desc).
161
+ def order_sorted_body
162
+ if desc?
163
+ column_sorted_body.reverse
164
+
165
+ elsif asc?
166
+ column_sorted_body
167
+
168
+ end
169
+ end
170
+
171
+ # @return [Array<Hash<Symbol => String>>] All of the results sorted by
172
+ # the :sort_column option. (Defaults to :avg).
173
+ def column_sorted_body
174
+ runs = options[:show_all_runs] ? previous_run : current_run
175
+ runs.keys.each_with_object([]) do |description, obj|
176
+ timings = previous_run[description]
177
+ size = Array(timings).size
178
+ sum = Array(timings).inject { |total, x| total + x }
179
+ obj << {
180
+ avg: (sum / size).round(9),
181
+ min: Array(timings).min.round(9),
182
+ max: Array(timings).max.round(9),
183
+ last: Array(timings).last.round(9),
184
+ desc: description,
185
+ }
186
+ end.sort_by { |k| k[sort_column] }
187
+ end
188
+
189
+ # @return [Hash]
190
+ def options
191
+ defaults.merge!(@options)
192
+ end
193
+
194
+ # @return [Fixnum] The number of tests to output to output to the screen
195
+ # after each run.
196
+ def show_count
197
+ options[:show_count]
198
+ end
199
+
200
+ # @return [Hash<String => Array<Float>]
201
+ def previous_run
202
+ @previous_run ||= YAML.load_file(previous_runs_filename)
203
+ end
204
+
205
+ # @return [String] The path to the file which contains all the durations
206
+ # for each test run. The previous runs file is in YAML format, using the
207
+ # test name for the key and an array containing the time taken to run
208
+ # this test for values.
209
+ def previous_runs_filename
210
+ options[:previous_runs_filename]
211
+ end
212
+
213
+ # Returns a boolean indicating whether a previous runs file exists.
214
+ #
215
+ # @return [Boolean]
216
+ def previously_ran?
217
+ File.exist?(previous_runs_filename)
218
+ end
219
+
220
+ # @return [String] The path to the file which contains the parsed test
221
+ # results. The results file contains a line for each test with the
222
+ # average time of the test, the minimum time the test took to run,
223
+ # the maximum time the test took to run and a description of the test
224
+ # (which is the test name as emitted by Minitest).
225
+ def report_filename
226
+ options[:report_filename]
227
+ end
228
+
229
+ # A barbaric way to find out how many runs are in the previous runs file;
230
+ # this method takes the first test listed, and counts its samples
231
+ # trusting (naively) all runs to be the same number of samples. This will
232
+ # produce incorrect averages when new tests are added, so it is advised
233
+ # to restart the statistics by removing the 'previous runs' file. A rake
234
+ # task is provided to make this more convenient.
235
+ #
236
+ # rake reset_statistics
237
+ #
238
+ # @return [Fixnum]
239
+ def samples
240
+ return 1 unless previous_run.first[1].is_a?(Array)
241
+
242
+ previous_run.first[1].size
243
+ end
244
+
245
+ # Creates a new 'previous runs' file, or updates the existing one with
246
+ # the latest timings.
247
+ #
248
+ # @return [void]
249
+ def create_or_update_previous_runs!
250
+ if previously_ran?
251
+ current_run.each do |description, elapsed|
252
+ new_times = if previous_run["#{description}"]
253
+ Array(previous_run["#{description}"]) << elapsed
254
+
255
+ else
256
+ Array(elapsed)
257
+
258
+ end
259
+
260
+ previous_run.store("#{description}", new_times)
261
+ end
262
+
263
+ File.write(previous_runs_filename, previous_run.to_yaml)
264
+
265
+ else
266
+
267
+ File.write(previous_runs_filename, current_run.to_yaml)
268
+
269
+ end
270
+ end
271
+
272
+ # Creates a new report file in the 'report_filename'. This file contains
273
+ # a line for each test of the following example format: (this is a single
274
+ # line despite explicit wrapping)
275
+ #
276
+ # Avg: 0.0555555 Min: 0.0498765 Max: 0.0612345 Last: 0.0499421
277
+ # Description: The test name
278
+ #
279
+ # Note however the timings are to 9 decimal places, and padded to 12
280
+ # characters and each label is coloured, Avg (yellow), Min (green),
281
+ # Max (red), Last (multi), and Description (blue). It looks pretty!
282
+ #
283
+ # The 'Last' label is special in that it will be colour coded depending
284
+ # on whether the last run was faster (bright green) or slower (bright red)
285
+ # or inconclusive (purple). This helps to identify changes on a per run
286
+ # basis.
287
+ #
288
+ # @return [void]
289
+ def create_new_report!
290
+ File.write(report_filename, report_title + report_body)
291
+ end
292
+
293
+ # Writes a number of tests (configured via the 'show_count' option) to the
294
+ # screen after creating the report. See '#create_new_report!' for example
295
+ # output information.
296
+ #
297
+ # @return [void]
298
+ def write_to_screen!
299
+ puts report_title
300
+ puts report_body.lines.take(show_count)
301
+ end
302
+
303
+ # @return [String] A yellow 'Avg:' label.
304
+ def avg_label
305
+ ANSI::Code.yellow('Avg:')
306
+ end
307
+
308
+ # @return [String] A blue 'Description:' label.
309
+ def des_label
310
+ ANSI::Code.blue('Description:')
311
+ end
312
+
313
+ # @return [String] A red 'Max:' label.
314
+ def max_label
315
+ ANSI::Code.red('Max:')
316
+ end
317
+
318
+ # @return [String] A green 'Min:' label.
319
+ def min_label
320
+ ANSI::Code.green('Min:')
321
+ end
322
+
323
+ # @param rating [Symbol] One of :faster, :slower or :inconclusive.
324
+ # @return [String] A purple 'Last:' label.
325
+ def run_label(rating)
326
+ case rating
327
+ when :faster then ANSI::Code.green('Last:')
328
+ when :slower then ANSI::Code.red('Last:')
329
+ else
330
+ ANSI::Code.magenta('Last:')
331
+ end
332
+ end
333
+
334
+ # @param run [Float] The last run time.
335
+ # @param min [Float] The minimum run time.
336
+ # @param max [Float] The maximum run time.
337
+ # @return [Symbol] One of :faster, :slower or :inconclusive.
338
+ def rate(run, min, max)
339
+ if run == min
340
+ :faster
341
+ elsif run == max
342
+ :slower
343
+ else
344
+ :inconclusive
345
+ end
346
+ end
347
+
348
+ # @return [Boolean] Whether the given :order option is :asc.
349
+ def asc?
350
+ order == :asc
351
+ end
352
+
353
+ # @return [Boolean] Whether the given :order option is :desc (default).
354
+ def desc?
355
+ order == :desc
356
+ end
357
+
358
+ # @raise [Minitest::Reporters::MeanTimeReporter::InvalidOrder]
359
+ # When the given :order option is invalid.
360
+ # @return [Symbol] The :order option, or by default; :desc.
361
+ def order
362
+ orders = [:desc, :asc]
363
+
364
+ if orders.include?(options[:order])
365
+ options[:order]
366
+
367
+ else
368
+ fail Minitest::Reporters::MeanTimeReporter::InvalidOrder,
369
+ "`:order` option must be one of #{orders.inspect}."
370
+
371
+ end
372
+ end
373
+
374
+ # @raise [Minitest::Reporters::MeanTimeReporter::InvalidSortColumn]
375
+ # When the given :sort_column option is invalid.
376
+ # @return [Symbol] The :sort_column option, or by default; :avg.
377
+ def sort_column
378
+ sort_columns = [:avg, :min, :max, :last]
379
+
380
+ if sort_columns.include?(options[:sort_column])
381
+ options[:sort_column]
382
+
383
+ else
384
+ fail Minitest::Reporters::MeanTimeReporter::InvalidSortColumn,
385
+ "`:sort_column` option must be one of #{sort_columns.inspect}."
386
+
387
+ end
388
+ end
389
+
390
+ end
391
+ end
392
+ end