minitest-heat 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,10 +22,10 @@ module Minitest
22
22
  end
23
23
  end
24
24
 
25
- attr_reader :test_location, :backtrace
25
+ attr_reader :test_definition_location, :backtrace
26
26
 
27
- def initialize(test_location, backtrace = [])
28
- @test_location = TestDefinition.new(*test_location)
27
+ def initialize(test_definition_location, backtrace = [])
28
+ @test_definition_location = TestDefinition.new(*test_definition_location)
29
29
  @backtrace = Backtrace.new(backtrace)
30
30
  end
31
31
 
@@ -45,9 +45,9 @@ module Minitest
45
45
  # test, and it raises an exception, then it's really a broken test rather than a proper
46
46
  # faiure.
47
47
  #
48
- # @return [Boolean] true if most relevant file is the same as the test location file
48
+ # @return [Boolean] true if final file in the backtrace is the same as the test location file
49
49
  def broken_test?
50
- !test_file.nil? && test_file == most_relevant_file
50
+ !test_file.nil? && test_file == final_file
51
51
  end
52
52
 
53
53
  # Knows if the failure occurred in the actual project source code—as opposed to the test or
@@ -59,6 +59,15 @@ module Minitest
59
59
  !source_code_file.nil? && !broken_test?
60
60
  end
61
61
 
62
+
63
+
64
+ # The final location of the stacktrace regardless of whether it's from within the project
65
+ #
66
+ # @return [String] the relative path to the file from the project root
67
+ def final_file
68
+ Pathname(final_location.pathname)
69
+ end
70
+
62
71
  # The file most likely to be the source of the underlying problem. Often, the most recent
63
72
  # backtrace files will be a gem or external library that's failing indirectly as a result
64
73
  # of a problem with local source code (not always, but frequently). In that case, the best
@@ -69,78 +78,76 @@ module Minitest
69
78
  Pathname(most_relevant_location.pathname)
70
79
  end
71
80
 
72
- # The line number of the `most_relevant_file` where the failure originated
81
+ # The final location from the stacktrace that is a test file
73
82
  #
74
- # @return [Integer] line number
75
- def most_relevant_failure_line
76
- most_relevant_location.line_number
83
+ # @return [String, nil] the relative path to the file from the project root
84
+ def test_file
85
+ Pathname(final_test_location.pathname)
77
86
  end
78
87
 
79
- # The final location of the stacktrace regardless of whether it's from within the project
88
+ # The final location from the stacktrace that is within the project directory
80
89
  #
81
- # @return [String] the relative path to the file from the project root
82
- def final_file
83
- Pathname(final_location.pathname)
84
- end
90
+ # @return [String, nil] the relative path to the file from the project root
91
+ def source_code_file
92
+ return nil if final_source_code_location.nil?
85
93
 
86
- # The line number of the `final_file` where the failure originated
87
- #
88
- # @return [Integer] line number
89
- def final_failure_line
90
- final_location.line_number
94
+ Pathname(final_source_code_location.pathname)
91
95
  end
92
96
 
93
- # The final location of the stacktrace regardless of whether it's from within the project
97
+ # The final location of the stacktrace from within the project (source code or test code)
94
98
  #
95
99
  # @return [String] the relative path to the file from the project root
96
100
  def project_file
97
- broken_test? ? test_file : source_code_file
101
+ return nil if project_location.nil?
102
+
103
+ Pathname(project_location.pathname)
98
104
  end
99
105
 
100
- # The line number of the `project_file` where the failure originated
106
+
107
+ # The line number of the `final_file` where the failure originated
101
108
  #
102
109
  # @return [Integer] line number
103
- def project_failure_line
104
- broken_test? ? test_failure_line || test_definition_line : source_code_failure_line
110
+ def final_failure_line
111
+ final_location.line_number
105
112
  end
106
113
 
107
- # The final location from the stacktrace that is within the project directory
114
+ # The line number of the `most_relevant_file` where the failure originated
108
115
  #
109
- # @return [String, nil] the relative path to the file from the project root
110
- def source_code_file
111
- return nil unless backtrace.source_code_entries.any?
112
-
113
- backtrace.final_source_code_location.pathname
116
+ # @return [Integer] line number
117
+ def most_relevant_failure_line
118
+ most_relevant_location.line_number
114
119
  end
115
120
 
116
- # The line number of the `source_code_file` where the failure originated
121
+ # The line number of the `test_file` where the test is defined
117
122
  #
118
123
  # @return [Integer] line number
119
- def source_code_failure_line
120
- return nil unless backtrace.source_code_entries.any?
121
-
122
- backtrace.final_source_code_location.line_number
124
+ def test_definition_line
125
+ test_definition_location.line_number
123
126
  end
124
127
 
125
- # The final location from the stacktrace that is within the project's test directory
128
+ # The line number from within the `test_file` test definition where the failure occurred
126
129
  #
127
- # @return [String, nil] the relative path to the file from the project root
128
- def test_file
129
- Pathname(test_location.pathname)
130
+ # @return [Integer] line number
131
+ def test_failure_line
132
+ final_test_location.line_number
130
133
  end
131
134
 
132
- # The line number of the `test_file` where the test is defined
135
+ # The line number of the `source_code_file` where the failure originated
133
136
  #
134
137
  # @return [Integer] line number
135
- def test_definition_line
136
- test_location.line_number
138
+ def source_code_failure_line
139
+ final_source_code_location&.line_number
137
140
  end
138
141
 
139
- # The line number from within the `test_file` test definition where the failure occurred
142
+ # The line number of the `project_file` where the failure originated
140
143
  #
141
144
  # @return [Integer] line number
142
- def test_failure_line
143
- backtrace.final_test_location&.line_number || test_definition_line
145
+ def project_failure_line
146
+ if !broken_test? && !source_code_file.nil?
147
+ source_code_failure_line
148
+ else
149
+ test_failure_line
150
+ end
144
151
  end
145
152
 
146
153
  # The line number from within the `test_file` test definition where the failure occurred
@@ -148,7 +155,7 @@ module Minitest
148
155
  # @return [Location] the last location from the backtrace or the test location if a backtrace
149
156
  # was not passed to the initializer
150
157
  def final_location
151
- backtrace? ? backtrace.final_location : test_location
158
+ backtrace.parsed_entries.any? ? backtrace.final_location : test_definition_location
152
159
  end
153
160
 
154
161
  # The file most likely to be the source of the underlying problem. Often, the most recent
@@ -159,22 +166,33 @@ module Minitest
159
166
  # @return [Array] file and line number of the most likely source of the problem
160
167
  def most_relevant_location
161
168
  [
162
- source_code_location,
163
- test_location,
169
+ final_source_code_location,
170
+ final_test_location,
164
171
  final_location
165
172
  ].compact.first
166
173
  end
167
174
 
168
- def project_location
169
- source_code_location || test_location
175
+ # Returns the final test location based on the backtrace if present. Otherwise falls back to
176
+ # the test location which represents the test definition.
177
+ #
178
+ # @return [Location] the final location from the test files
179
+ def final_test_location
180
+ backtrace.final_test_location || test_definition_location
170
181
  end
171
182
 
172
- def source_code_location
183
+ # Returns the final source code location based on the backtrace
184
+ #
185
+ # @return [Location] the final location from the source code files
186
+ def final_source_code_location
173
187
  backtrace.final_source_code_location
174
188
  end
175
189
 
176
- def backtrace?
177
- backtrace.parsed_entries.any?
190
+ # Returns the final project location based on the backtrace if present. Otherwise falls back
191
+ # to the test location which represents the test definition.
192
+ #
193
+ # @return [Location] the final location from the project files
194
+ def project_location
195
+ backtrace.final_project_location || test_definition_location
178
196
  end
179
197
  end
180
198
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Minitest
4
4
  module Heat
5
+ # Structured approach to collecting the locations of issues for generating a heat map
5
6
  class Map
6
7
  MAXIMUM_FILES_TO_SHOW = 5
7
8
 
@@ -11,18 +12,30 @@ module Minitest
11
12
  @hits = {}
12
13
  end
13
14
 
15
+ # Records a hit to the list of files and issue types
16
+ # @param filename [String] the unique path and file name for recordings hits
17
+ # @param line_number [Integer] the line number where the issue was encountered
18
+ # @param type [Symbol] the type of issue that was encountered (i.e. :failure, :error, etc.)
19
+ #
20
+ # @return [void]
14
21
  def add(filename, line_number, type)
15
22
  @hits[filename] ||= Hit.new(filename)
16
23
 
17
- @hits[filename].log(type, line_number)
24
+ @hits[filename].log(type.to_sym, line_number)
18
25
  end
19
26
 
27
+ # Returns a subset of affected files to keep the list from being overwhelming
28
+ #
29
+ # @return [Array] the list of files and the line numbers for each encountered issue type
20
30
  def file_hits
21
31
  hot_files.take(MAXIMUM_FILES_TO_SHOW)
22
32
  end
23
33
 
24
34
  private
25
35
 
36
+ # Sorts the files by hit "weight" so that the most problematic files are at the beginning
37
+ #
38
+ # @return [Array] the collection of files that encountred issues
26
39
  def hot_files
27
40
  hits.values.sort_by(&:weight).reverse
28
41
  end
@@ -23,13 +23,9 @@ module Minitest
23
23
  # Iterate over the selected lines from the backtrace
24
24
  backtrace_entries.each do |backtrace_entry|
25
25
  # Get the source code for the line from the backtrace
26
- parts = [
27
- indentation_token,
28
- path_token(backtrace_entry),
29
- *file_and_line_number_tokens(backtrace_entry),
30
- source_code_line_token(backtrace_entry.source_code)
31
- ]
26
+ parts = backtrace_line_tokens(backtrace_entry)
32
27
 
28
+ # If it's the most recently modified file in the trace, add the token for that
33
29
  parts << file_freshness(backtrace_entry) if most_recently_modified?(backtrace_entry)
34
30
 
35
31
  @tokens << parts
@@ -57,6 +53,15 @@ module Minitest
57
53
 
58
54
  private
59
55
 
56
+ def backtrace_line_tokens(backtrace_entry)
57
+ [
58
+ indentation_token,
59
+ path_token(backtrace_entry),
60
+ *file_and_line_number_tokens(backtrace_entry),
61
+ source_code_line_token(backtrace_entry.source_code)
62
+ ]
63
+ end
64
+
60
65
  def all_backtrace_entries_from_project?
61
66
  backtrace_entries.all? { |line| line.path.to_s.include?(project_root_dir) }
62
67
  end
@@ -123,7 +128,7 @@ module Minitest
123
128
  end
124
129
 
125
130
  def style_for(path)
126
- style = path.to_s.include?(Dir.pwd) ? :default : :muted
131
+ path.to_s.include?(Dir.pwd) ? :default : :muted
127
132
  end
128
133
  end
129
134
  end
@@ -3,7 +3,8 @@
3
3
  module Minitest
4
4
  module Heat
5
5
  class Output
6
- class Issue
6
+ # Formats issues to output based on the issue type
7
+ class Issue # rubocop:disable Metrics/ClassLength
7
8
  attr_accessor :issue
8
9
 
9
10
  def initialize(issue)
@@ -77,11 +78,43 @@ module Minitest
77
78
  end
78
79
 
79
80
  def headline_tokens
80
- [[issue.type, issue.label], spacer_token, [:default, issue.test_name]]
81
+ [[issue.type, label(issue)], spacer_token, [:default, test_name(issue)]]
82
+ end
83
+
84
+ def test_name(issue)
85
+ test_prefix = 'test_'
86
+ identifier = issue.test_identifier
87
+
88
+ if identifier.start_with?(test_prefix)
89
+ identifier.delete_prefix(test_prefix).gsub('_', ' ').capitalize
90
+ else
91
+ identifier
92
+ end
93
+ end
94
+
95
+ def label(issue)
96
+ if issue.error? && issue.in_test?
97
+ # When the exception came out of the test itself, that's a different kind of exception
98
+ # that really only indicates there's a problem with the code in the test. It's kind of
99
+ # between an error and a test.
100
+ 'Broken Test'
101
+ elsif issue.error?
102
+ 'Error'
103
+ elsif issue.skipped?
104
+ 'Skipped'
105
+ elsif issue.painful?
106
+ 'Passed but Very Slow'
107
+ elsif issue.slow?
108
+ 'Passed but Slow'
109
+ elsif !issue.passed?
110
+ 'Failure'
111
+ else
112
+ 'Success'
113
+ end
81
114
  end
82
115
 
83
116
  def test_name_and_class_tokens
84
- [[:default, issue.test_class], *test_location_tokens ]
117
+ [[:default, issue.test_class], *test_location_tokens]
85
118
  end
86
119
 
87
120
  def backtrace_tokens
@@ -107,12 +140,12 @@ module Minitest
107
140
  end
108
141
 
109
142
  def summary_tokens
110
- [[:italicized, issue.summary.delete_suffix("---------------")]]
143
+ [[:italicized, issue.summary.delete_suffix('---------------').strip]]
111
144
  end
112
145
 
113
146
  def slowness_summary_tokens
114
147
  [
115
- [:bold, issue.slowness],
148
+ [:bold, slowness(issue)],
116
149
  spacer_token,
117
150
  [:default, issue.location.test_file.to_s.delete_prefix(Dir.pwd)],
118
151
  [:muted, ':'],
@@ -120,6 +153,10 @@ module Minitest
120
153
  ]
121
154
  end
122
155
 
156
+ def slowness(issue)
157
+ "#{issue.execution_time.round(2)}s"
158
+ end
159
+
123
160
  def newline_tokens
124
161
  []
125
162
  end
@@ -155,7 +192,6 @@ module Minitest
155
192
  def arrow_token
156
193
  Output::TOKENS[:muted_arrow]
157
194
  end
158
-
159
195
  end
160
196
  end
161
197
  end
@@ -3,6 +3,7 @@
3
3
  module Minitest
4
4
  module Heat
5
5
  class Output
6
+ # Generates the tokens to output the resulting heat map
6
7
  class Map
7
8
  attr_accessor :results
8
9
 
@@ -34,8 +35,10 @@ module Minitest
34
35
  end
35
36
 
36
37
  def relevant_issue_types
38
+ # These are always relevant.
37
39
  issue_types = %i[error broken failure]
38
40
 
41
+ # These are only relevant if there aren't more serious isues.
39
42
  issue_types << :skipped unless results.problems?
40
43
  issue_types << :painful unless results.problems? || results.skips.any?
41
44
  issue_types << :slow unless results.problems? || results.skips.any?
@@ -44,7 +47,7 @@ module Minitest
44
47
  end
45
48
 
46
49
  def pathname(file)
47
- directory = "#{file.pathname.dirname.to_s.delete_prefix(Dir.pwd)}/"
50
+ directory = "#{file.pathname.dirname.to_s.delete_prefix(Dir.pwd)}/".delete_prefix('/')
48
51
  filename = file.pathname.basename.to_s
49
52
 
50
53
  [
@@ -57,18 +60,29 @@ module Minitest
57
60
  def hit_line_numbers(file, issue_type)
58
61
  numbers = []
59
62
  line_numbers_for_issue_type = file.issues.fetch(issue_type) { [] }
60
- line_numbers_for_issue_type.sort.map do |line_number|
63
+ line_numbers_for_issue_type.map do |line_number|
61
64
  numbers << [issue_type, "#{line_number} "]
62
65
  end
66
+
63
67
  numbers
64
68
  end
65
69
 
66
70
  def line_numbers(file)
67
71
  line_number_tokens = []
72
+
73
+ # Merge the hits for all issue types into one list
68
74
  relevant_issue_types.each do |issue_type|
69
75
  line_number_tokens += hit_line_numbers(file, issue_type)
70
76
  end
71
- line_number_tokens.compact.sort_by { |number_token| number_token[1] }
77
+
78
+ # Sort the collected group of line number hits so they're in order
79
+ line_number_tokens.compact.sort do |a, b|
80
+ # Ensure the line numbers are integers for sorting (otherwise '100' comes before '12')
81
+ first_line_number = Integer(a[1].strip)
82
+ second_line_number = Integer(b[1].strip)
83
+
84
+ first_line_number <=> second_line_number
85
+ end
72
86
  end
73
87
  end
74
88
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Minitest
4
4
  module Heat
5
- # Friendly API for printing nicely-formatted output to the console
6
5
  class Output
6
+ # Friendly API for printing consistent markers for the various issue types
7
7
  class Marker
8
8
  SYMBOLS = {
9
9
  success: '·',
@@ -12,7 +12,8 @@ module Minitest
12
12
  broken: 'B',
13
13
  error: 'E',
14
14
  skipped: 'S',
15
- failure: 'F'
15
+ failure: 'F',
16
+ reporter: '✖'
16
17
  }.freeze
17
18
 
18
19
  STYLES = {
@@ -22,7 +23,8 @@ module Minitest
22
23
  broken: :error,
23
24
  error: :error,
24
25
  skipped: :skipped,
25
- failure: :failure
26
+ failure: :failure,
27
+ reporter: :error
26
28
  }.freeze
27
29
 
28
30
  attr_accessor :issue_type
@@ -3,6 +3,7 @@
3
3
  module Minitest
4
4
  module Heat
5
5
  class Output
6
+ # Generates the output tokens to display the results summary
6
7
  class Results
7
8
  extend Forwardable
8
9
 
@@ -90,7 +91,7 @@ module Minitest
90
91
  end
91
92
 
92
93
  def test_count_token
93
- [:default, "#{pluralize(timer.test_count, 'test')}"]
94
+ [:default, pluralize(timer.test_count, 'test').to_s]
94
95
  end
95
96
 
96
97
  def tests_performance_token
@@ -98,7 +99,7 @@ module Minitest
98
99
  end
99
100
 
100
101
  def assertions_count_token
101
- [:default, "#{pluralize(timer.assertion_count, 'assertion')}"]
102
+ [:default, pluralize(timer.assertion_count, 'assertion').to_s]
102
103
  end
103
104
 
104
105
  def assertions_performance_token
@@ -3,7 +3,7 @@
3
3
  module Minitest
4
4
  module Heat
5
5
  class Output
6
- # Builds the collection of tokens representing a specific set of source code lines
6
+ # Generates the tokens representing a specific set of source code lines
7
7
  class SourceCode
8
8
  DEFAULT_LINE_COUNT = 3
9
9
  DEFAULT_INDENTATION_SPACES = 2
@@ -2,8 +2,9 @@
2
2
 
3
3
  module Minitest
4
4
  module Heat
5
- # Friendly API for printing nicely-formatted output to the console
6
5
  class Output
6
+ # Provides a convenient interface for creating console-friendly output while ensuring
7
+ # consistency in the applied styles.
7
8
  class Token
8
9
  class InvalidStyle < ArgumentError; end
9
10
 
@@ -15,14 +15,14 @@ module Minitest
15
15
  SYMBOLS = {
16
16
  middot: '·',
17
17
  arrow: '➜',
18
- lead: '|',
18
+ lead: '|'
19
19
  }.freeze
20
20
 
21
21
  TOKENS = {
22
- spacer: [:muted, " #{SYMBOLS[:middot]} "],
22
+ spacer: [:muted, " #{SYMBOLS[:middot]} "],
23
23
  muted_arrow: [:muted, " #{SYMBOLS[:arrow]} "],
24
- muted_lead: [:muted, "#{SYMBOLS[:lead]} "],
25
- }
24
+ muted_lead: [:muted, "#{SYMBOLS[:lead]} "]
25
+ }.freeze
26
26
 
27
27
  attr_reader :stream
28
28
 
@@ -42,8 +42,30 @@ module Minitest
42
42
  end
43
43
  alias newline puts
44
44
 
45
+ def issues_list(results)
46
+ # A couple of blank lines to create some breathing room
47
+ newline
48
+ newline
49
+
50
+ # Issues start with the least critical and go up to the most critical so that the most
51
+ # pressing issues are displayed at the bottom of the report in order to reduce scrolling.
52
+ # This way, as you fix issues, the list gets shorter, and eventually the least critical
53
+ # issues will be displayed without scrolling once more problematic issues are resolved.
54
+ %i[slows painfuls skips failures brokens errors].each do |issue_category|
55
+ next unless show?(issue_category, results)
56
+
57
+ results.send(issue_category).each { |issue| issue_details(issue) }
58
+ end
59
+ rescue => e
60
+ message = "Sorry, but Minitest Heat couldn't display the details of any failures."
61
+ exception_guidance(message, e)
62
+ end
63
+
45
64
  def issue_details(issue)
46
65
  print_tokens Minitest::Heat::Output::Issue.new(issue).tokens
66
+ rescue => e
67
+ message = "Sorry, but Minitest Heat couldn't display output for a failure."
68
+ exception_guidance(message, e)
47
69
  end
48
70
 
49
71
  def marker(issue_type)
@@ -53,15 +75,49 @@ module Minitest
53
75
  def compact_summary(results, timer)
54
76
  newline
55
77
  print_tokens ::Minitest::Heat::Output::Results.new(results, timer).tokens
78
+ rescue => e
79
+ message = "Sorry, but Minitest Heat couldn't display the summary."
80
+ exception_guidance(message, e)
56
81
  end
57
82
 
58
83
  def heat_map(map)
59
84
  newline
60
85
  print_tokens ::Minitest::Heat::Output::Map.new(map).tokens
86
+ newline
87
+ rescue => e
88
+ message = "Sorry, but Minitest Heat couldn't display the heat map."
89
+ exception_guidance(message, e)
90
+ end
91
+
92
+ def exception_guidance(message, exception)
93
+ newline
94
+ puts "#{message} Disabling Minitest Heat can get you back on track until the problem can be fixed."
95
+ puts "Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues"
96
+ puts "#{exception.message}:"
97
+ exception.backtrace.each do |line|
98
+ puts " #{line}"
99
+ end
100
+ newline
61
101
  end
62
102
 
63
103
  private
64
104
 
105
+ def no_problems?(results)
106
+ !results.problems?
107
+ end
108
+
109
+ def no_problems_or_skips?(results)
110
+ !results.problems? && results.skips.none?
111
+ end
112
+
113
+ def show?(issue_category, results)
114
+ case issue_category
115
+ when :skips then no_problems?(results)
116
+ when :painfuls, :slows then no_problems_or_skips?(results)
117
+ else true
118
+ end
119
+ end
120
+
65
121
  def style_enabled?
66
122
  stream.tty?
67
123
  end
@@ -11,9 +11,24 @@ module Minitest
11
11
  @heat_map = Heat::Map.new
12
12
  end
13
13
 
14
+ # Logs an issue to the results for later reporting
15
+ # @param issue [Issue] the issue generated from a given test result
16
+ #
17
+ # @return [type] [description]
14
18
  def record(issue)
19
+ # Record everything—even if it's a success
15
20
  @issues.push(issue)
16
- @heat_map.add(*issue.to_hit) if issue.hit?
21
+
22
+ # If it's not a genuine problem, we're done here, otherwise update the heat map
23
+ update_heat_map(issue) if issue.hit?
24
+ end
25
+
26
+ def update_heat_map(issue)
27
+ # Get the elements we need to generate a heat map entry
28
+ pathname = issue.location.project_file.to_s
29
+ line_number = issue.location.project_failure_line.to_i
30
+
31
+ @heat_map.add(pathname, line_number, issue.type)
17
32
  end
18
33
 
19
34
  def problems?
@@ -37,11 +52,11 @@ module Minitest
37
52
  end
38
53
 
39
54
  def painfuls
40
- @painfuls ||= select_issues(:painful).sort_by(&:time).reverse
55
+ @painfuls ||= select_issues(:painful).sort_by(&:execution_time).reverse
41
56
  end
42
57
 
43
58
  def slows
44
- @slows ||= select_issues(:slow).sort_by(&:time).reverse
59
+ @slows ||= select_issues(:slow).sort_by(&:execution_time).reverse
45
60
  end
46
61
 
47
62
  private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Minitest
4
4
  module Heat
5
- VERSION = '0.0.9'
5
+ VERSION = '0.0.10'
6
6
  end
7
7
  end
data/lib/minitest/heat.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require_relative 'heat/backtrace'
4
4
  require_relative 'heat/hit'
5
5
  require_relative 'heat/issue'
6
- require_relative 'heat/line'
7
6
  require_relative 'heat/location'
8
7
  require_relative 'heat/map'
9
8
  require_relative 'heat/output'
@@ -13,7 +12,8 @@ require_relative 'heat/timer'
13
12
  require_relative 'heat/version'
14
13
 
15
14
  module Minitest
16
- # Custom minitest reporter just for Reviewer. Focuses on printing directly actionable guidance.
15
+ # Custom Minitest reporter focused on generating output designed around efficiently identifying
16
+ # issues and potential solutions
17
17
  # - Colorize the Output
18
18
  # - What files had the most errors?
19
19
  # - Show the most impacted areas first.