minitest-heat 0.0.10 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -6
- data/README.md +48 -13
- data/examples/exceptions.png +0 -0
- data/examples/failures.png +0 -0
- data/examples/map.png +0 -0
- data/examples/markers.png +0 -0
- data/examples/skips.png +0 -0
- data/examples/slows.png +0 -0
- data/lib/minitest/heat/backtrace/line_parser.rb +25 -0
- data/lib/minitest/heat/backtrace.rb +21 -59
- data/lib/minitest/heat/hit.rb +18 -6
- data/lib/minitest/heat/issue.rb +35 -17
- data/lib/minitest/heat/location.rb +113 -132
- data/lib/minitest/heat/locations.rb +105 -0
- data/lib/minitest/heat/map.rb +3 -4
- data/lib/minitest/heat/output/backtrace.rb +88 -70
- data/lib/minitest/heat/output/issue.rb +56 -83
- data/lib/minitest/heat/output/map.rb +116 -28
- data/lib/minitest/heat/output.rb +27 -13
- data/lib/minitest/heat/results.rb +11 -6
- data/lib/minitest/heat/source.rb +1 -1
- data/lib/minitest/heat/version.rb +1 -1
- data/lib/minitest/heat.rb +1 -0
- data/lib/minitest/heat_plugin.rb +1 -1
- data/lib/minitest/heat_reporter.rb +13 -6
- metadata +11 -4
- data/lib/minitest/heat/backtrace/line.rb +0 -118
@@ -5,36 +5,25 @@ module Minitest
|
|
5
5
|
class Output
|
6
6
|
# Formats issues to output based on the issue type
|
7
7
|
class Issue # rubocop:disable Metrics/ClassLength
|
8
|
-
attr_accessor :issue
|
8
|
+
attr_accessor :issue, :locations
|
9
9
|
|
10
10
|
def initialize(issue)
|
11
11
|
@issue = issue
|
12
|
+
@locations = issue.locations
|
12
13
|
end
|
13
14
|
|
14
15
|
def tokens
|
15
16
|
case issue.type
|
16
|
-
when :error then
|
17
|
-
when :
|
18
|
-
when :
|
19
|
-
when :
|
20
|
-
when :painful then painful_tokens
|
21
|
-
when :slow then slow_tokens
|
17
|
+
when :error, :broken then exception_tokens
|
18
|
+
when :failure then failure_tokens
|
19
|
+
when :skipped then skipped_tokens
|
20
|
+
when :painful, :slow then slow_tokens
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
24
|
private
|
26
25
|
|
27
|
-
def
|
28
|
-
[
|
29
|
-
headline_tokens,
|
30
|
-
test_location_tokens,
|
31
|
-
summary_tokens,
|
32
|
-
*backtrace_tokens,
|
33
|
-
newline_tokens
|
34
|
-
]
|
35
|
-
end
|
36
|
-
|
37
|
-
def broken_tokens
|
26
|
+
def exception_tokens
|
38
27
|
[
|
39
28
|
headline_tokens,
|
40
29
|
test_location_tokens,
|
@@ -61,14 +50,6 @@ module Minitest
|
|
61
50
|
]
|
62
51
|
end
|
63
52
|
|
64
|
-
def painful_tokens
|
65
|
-
[
|
66
|
-
headline_tokens,
|
67
|
-
slowness_summary_tokens,
|
68
|
-
newline_tokens
|
69
|
-
]
|
70
|
-
end
|
71
|
-
|
72
53
|
def slow_tokens
|
73
54
|
[
|
74
55
|
headline_tokens,
|
@@ -78,9 +59,14 @@ module Minitest
|
|
78
59
|
end
|
79
60
|
|
80
61
|
def headline_tokens
|
81
|
-
[
|
62
|
+
[label_token(issue), spacer_token, [:default, test_name(issue)]]
|
82
63
|
end
|
83
64
|
|
65
|
+
# Creates a display-friendly version of the test name with underscores removed and the
|
66
|
+
# first letter capitalized regardless of the formatt used for the test definition
|
67
|
+
# @param issue [Issue] the issue to use to generate the test name
|
68
|
+
#
|
69
|
+
# @return [String] the cleaned up version of the test name
|
84
70
|
def test_name(issue)
|
85
71
|
test_prefix = 'test_'
|
86
72
|
identifier = issue.test_identifier
|
@@ -92,50 +78,39 @@ module Minitest
|
|
92
78
|
end
|
93
79
|
end
|
94
80
|
|
95
|
-
def
|
96
|
-
|
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
|
+
def label_token(issue)
|
82
|
+
[issue.type, issue_label(issue.type)]
|
114
83
|
end
|
115
84
|
|
116
85
|
def test_name_and_class_tokens
|
117
86
|
[[:default, issue.test_class], *test_location_tokens]
|
118
87
|
end
|
119
88
|
|
120
|
-
def backtrace_tokens
|
121
|
-
backtrace = ::Minitest::Heat::Output::Backtrace.new(issue.location)
|
122
|
-
|
123
|
-
backtrace.tokens
|
124
|
-
end
|
125
|
-
|
126
89
|
def test_location_tokens
|
127
|
-
[
|
90
|
+
[
|
91
|
+
[:default, locations.test_definition.relative_filename],
|
92
|
+
[:muted, ':'],
|
93
|
+
[:default, locations.test_definition.line_number],
|
94
|
+
arrow_token,
|
95
|
+
[:default, locations.test_failure.line_number],
|
96
|
+
[:muted, "\n #{locations.test_failure.source_code.line.strip}"]
|
97
|
+
]
|
128
98
|
end
|
129
99
|
|
130
100
|
def location_tokens
|
131
|
-
[
|
101
|
+
[
|
102
|
+
[:default, locations.most_relevant.relative_filename],
|
103
|
+
[:muted, ':'],
|
104
|
+
[:default, locations.most_relevant.line_number],
|
105
|
+
[:muted, "\n #{locations.most_relevant.source_code.line.strip}"]
|
106
|
+
]
|
132
107
|
end
|
133
108
|
|
134
109
|
def source_tokens
|
135
|
-
filename =
|
136
|
-
line_number =
|
137
|
-
|
110
|
+
filename = locations.project.filename
|
111
|
+
line_number = locations.project.line_number
|
138
112
|
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
113
|
+
|
139
114
|
[[:muted, " #{Output::SYMBOLS[:arrow]} `#{source.line.strip}`"]]
|
140
115
|
end
|
141
116
|
|
@@ -147,9 +122,10 @@ module Minitest
|
|
147
122
|
[
|
148
123
|
[:bold, slowness(issue)],
|
149
124
|
spacer_token,
|
150
|
-
[:default,
|
125
|
+
[:default, locations.test_definition.relative_path],
|
126
|
+
[:default, locations.test_definition.filename],
|
151
127
|
[:muted, ':'],
|
152
|
-
[:default,
|
128
|
+
[:default, locations.test_definition.line_number]
|
153
129
|
]
|
154
130
|
end
|
155
131
|
|
@@ -161,30 +137,6 @@ module Minitest
|
|
161
137
|
[]
|
162
138
|
end
|
163
139
|
|
164
|
-
def most_relevant_short_location
|
165
|
-
issue.location.most_relevant_file.to_s.delete_prefix("#{Dir.pwd}/")
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_file_short_location
|
169
|
-
issue.location.test_file.to_s.delete_prefix("#{Dir.pwd}/")
|
170
|
-
end
|
171
|
-
|
172
|
-
def most_relevant_line_source
|
173
|
-
filename = issue.location.project_file
|
174
|
-
line_number = issue.location.project_failure_line
|
175
|
-
|
176
|
-
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
177
|
-
"\n #{source.line.strip}"
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_line_source
|
181
|
-
filename = issue.location.test_file
|
182
|
-
line_number = issue.location.test_failure_line
|
183
|
-
|
184
|
-
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
185
|
-
"\n #{source.line.strip}"
|
186
|
-
end
|
187
|
-
|
188
140
|
def spacer_token
|
189
141
|
Output::TOKENS[:spacer]
|
190
142
|
end
|
@@ -192,6 +144,27 @@ module Minitest
|
|
192
144
|
def arrow_token
|
193
145
|
Output::TOKENS[:muted_arrow]
|
194
146
|
end
|
147
|
+
|
148
|
+
def backtrace_tokens
|
149
|
+
@backtrace_tokens ||= ::Minitest::Heat::Output::Backtrace.new(locations).tokens
|
150
|
+
end
|
151
|
+
|
152
|
+
# The string to use to describe the failure type when displaying results/
|
153
|
+
# @param issue_type [Symbol] the symbol representing the issue's failure type
|
154
|
+
#
|
155
|
+
# @return [String] the display-friendly string describing the failure reason
|
156
|
+
def issue_label(issue_type)
|
157
|
+
case issue_type
|
158
|
+
when :error then 'Error'
|
159
|
+
when :broken then 'Broken Test'
|
160
|
+
when :failure then 'Failure'
|
161
|
+
when :skipped then 'Skipped'
|
162
|
+
when :slow then 'Passed but Slow'
|
163
|
+
when :painful then 'Passed but Very Slow'
|
164
|
+
when :passed then 'Success'
|
165
|
+
else 'Unknown'
|
166
|
+
end
|
167
|
+
end
|
195
168
|
end
|
196
169
|
end
|
197
170
|
end
|
@@ -13,16 +13,36 @@ module Minitest
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def tokens
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
results.heat_map.file_hits.each do |hit|
|
17
|
+
# Focus on the relevant issues based on most significant problems. i.e. If there are
|
18
|
+
# legitimate failures or errors, skips and slows aren't relevant
|
19
|
+
next unless relevant_issue_types?(hit)
|
19
20
|
|
20
|
-
|
21
|
+
# Add a new line
|
22
|
+
@tokens << [[:muted, ""]]
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
# Build the summary line for the file
|
25
|
+
@tokens << file_summary_tokens(hit)
|
26
|
+
|
27
|
+
# Get the set of line numbers that appear more than once
|
28
|
+
repeated_line_numbers = find_repeated_line_numbers_in(hit)
|
29
|
+
|
30
|
+
# Only display more details if the same line number shows up more than once
|
31
|
+
next unless repeated_line_numbers.any?
|
32
|
+
|
33
|
+
repeated_line_numbers.each do |line_number|
|
34
|
+
# Get the backtraces for the given line numbers
|
35
|
+
traces = hit.lines[line_number.to_s]
|
36
|
+
|
37
|
+
# If there aren't any traces there's no way to provide additional details
|
38
|
+
break unless traces.any?
|
39
|
+
|
40
|
+
# A short summary explaining the details that will follow
|
41
|
+
@tokens << [[:muted, " Issues on Line #{line_number} initially triggered from these locations:"]]
|
42
|
+
|
43
|
+
# The last relevant location for each error's backtrace
|
44
|
+
@tokens += origination_sources(traces)
|
45
|
+
end
|
26
46
|
end
|
27
47
|
|
28
48
|
@tokens
|
@@ -30,8 +50,34 @@ module Minitest
|
|
30
50
|
|
31
51
|
private
|
32
52
|
|
33
|
-
def
|
34
|
-
|
53
|
+
def origination_sources(traces)
|
54
|
+
# 1. Sort the traces by the most recent line number so they're displayed in numeric order
|
55
|
+
# 2. Get the final relevant location from the trace
|
56
|
+
traces.
|
57
|
+
sort_by { |trace| trace.locations.last.line_number }.
|
58
|
+
map { |trace| origination_location_token(trace) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def file_summary_tokens(hit)
|
62
|
+
pathname_tokens = pathname(hit)
|
63
|
+
line_number_list_tokens = sorted_line_number_list(hit)
|
64
|
+
|
65
|
+
[*pathname_tokens, *line_number_list_tokens]
|
66
|
+
end
|
67
|
+
|
68
|
+
def origination_location_token(trace)
|
69
|
+
# The earliest project line from the backtrace—this is probabyl wholly incorrect in terms
|
70
|
+
# of what would be the most helpful line to display, but it's a start.
|
71
|
+
location = trace.locations.last
|
72
|
+
|
73
|
+
[
|
74
|
+
[:muted, " #{Output::SYMBOLS[:arrow]} "],
|
75
|
+
[:default, location.relative_filename],
|
76
|
+
[:muted, ':'],
|
77
|
+
[:default, location.line_number],
|
78
|
+
[:muted, " in #{location.container}"],
|
79
|
+
[:muted, " #{Output::SYMBOLS[:arrow]} `#{location.source_code.line.strip}`"],
|
80
|
+
]
|
35
81
|
end
|
36
82
|
|
37
83
|
def relevant_issue_types
|
@@ -46,37 +92,79 @@ module Minitest
|
|
46
92
|
issue_types
|
47
93
|
end
|
48
94
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
95
|
+
def relevant_issue_types?(hit)
|
96
|
+
# The intersection of which issue types are relevant based on the context and which issues
|
97
|
+
# matc those issue types
|
98
|
+
intersection_issue_types = relevant_issue_types & hit.issues.keys
|
52
99
|
|
53
|
-
|
54
|
-
[:default, directory],
|
55
|
-
[:bold, filename],
|
56
|
-
[:default, ' · ']
|
57
|
-
]
|
100
|
+
intersection_issue_types.any?
|
58
101
|
end
|
59
102
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
103
|
+
def find_repeated_line_numbers_in(hit)
|
104
|
+
repeated_line_numbers = []
|
105
|
+
|
106
|
+
hit.lines.each_pair do |line_number, traces|
|
107
|
+
# If there aren't multiple traces for a line number, it's not a repeat
|
108
|
+
next unless traces.size > 1
|
109
|
+
|
110
|
+
repeated_line_numbers << Integer(line_number)
|
65
111
|
end
|
66
112
|
|
67
|
-
|
113
|
+
repeated_line_numbers.sort
|
114
|
+
end
|
115
|
+
|
116
|
+
def pathname(hit)
|
117
|
+
directory = hit.pathname.dirname.to_s.delete_prefix("#{Dir.pwd}/")
|
118
|
+
filename = hit.pathname.basename.to_s
|
119
|
+
|
120
|
+
[
|
121
|
+
[:default, "#{directory}/"],
|
122
|
+
[:bold, filename],
|
123
|
+
[:default, ' · ']
|
124
|
+
]
|
68
125
|
end
|
69
126
|
|
70
|
-
|
127
|
+
# Gets the list of line numbers for a given hit location (i.e. file) so they can be
|
128
|
+
# displayed after the file name to show which lines were problematic
|
129
|
+
# @param hit [Hit] the instance to extract line numbers from
|
130
|
+
#
|
131
|
+
# @return [Array<Symbol,String>] [description]
|
132
|
+
def line_number_tokens_for_hit(hit)
|
71
133
|
line_number_tokens = []
|
72
134
|
|
73
|
-
# Merge the hits for all issue types into one list
|
74
135
|
relevant_issue_types.each do |issue_type|
|
75
|
-
|
136
|
+
# Retrieve any line numbers for the issue type
|
137
|
+
line_numbers_for_issue_type = hit.issues.fetch(issue_type) { [] }
|
138
|
+
|
139
|
+
# Build the list of tokens representing styled line numbers
|
140
|
+
line_numbers_for_issue_type.each do |line_number|
|
141
|
+
line_number_tokens << line_number_token(issue_type, line_number)
|
142
|
+
end
|
76
143
|
end
|
77
144
|
|
145
|
+
line_number_tokens.compact
|
146
|
+
end
|
147
|
+
|
148
|
+
# Builds a token representing a styled line number
|
149
|
+
#
|
150
|
+
# @param style [Symbol] the relevant display style for the issue
|
151
|
+
# @param line_number [Integer] the affected line number
|
152
|
+
#
|
153
|
+
# @return [Array<Symbol,Integer>] array token representing the line number and issue type
|
154
|
+
def line_number_token(style, line_number)
|
155
|
+
[style, "#{line_number} "]
|
156
|
+
end
|
157
|
+
|
158
|
+
# Sorts line number tokens so that line numbers are displayed in order regardless of their
|
159
|
+
# underlying issue type
|
160
|
+
#
|
161
|
+
# @param hit [Hit] the instance of the hit file details to build the heat map entry
|
162
|
+
#
|
163
|
+
# @return [Array] the arrays representing the line number tokens to display next to a file
|
164
|
+
# name in the heat map. ex [[:error, 12], [:falure, 13]]
|
165
|
+
def sorted_line_number_list(hit)
|
78
166
|
# Sort the collected group of line number hits so they're in order
|
79
|
-
|
167
|
+
line_number_tokens_for_hit(hit).sort do |a, b|
|
80
168
|
# Ensure the line numbers are integers for sorting (otherwise '100' comes before '12')
|
81
169
|
first_line_number = Integer(a[1].strip)
|
82
170
|
second_line_number = Integer(b[1].strip)
|
data/lib/minitest/heat/output.rb
CHANGED
@@ -11,7 +11,7 @@ require_relative 'output/token'
|
|
11
11
|
module Minitest
|
12
12
|
module Heat
|
13
13
|
# Friendly API for printing nicely-formatted output to the console
|
14
|
-
class Output
|
14
|
+
class Output # rubocop:disable Metrics/ClassLength
|
15
15
|
SYMBOLS = {
|
16
16
|
middot: '·',
|
17
17
|
arrow: '➜',
|
@@ -48,23 +48,26 @@ module Minitest
|
|
48
48
|
newline
|
49
49
|
|
50
50
|
# Issues start with the least critical and go up to the most critical so that the most
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
51
|
+
# pressing issues are displayed at the bottom of the report in order to reduce scrolling.
|
52
|
+
#
|
53
|
+
# This way, as you fix issues, the list gets shorter, and eventually the least critical
|
54
|
+
# issues will be displayed without scrolling once more problematic issues are resolved.
|
54
55
|
%i[slows painfuls skips failures brokens errors].each do |issue_category|
|
56
|
+
# Only show categories for the most pressing issues after the suite runs, otherwise,
|
57
|
+
# suppress them until the more critical issues are resolved.
|
55
58
|
next unless show?(issue_category, results)
|
56
59
|
|
57
60
|
results.send(issue_category).each { |issue| issue_details(issue) }
|
58
61
|
end
|
59
|
-
rescue => e
|
62
|
+
rescue StandardError => e
|
60
63
|
message = "Sorry, but Minitest Heat couldn't display the details of any failures."
|
61
64
|
exception_guidance(message, e)
|
62
65
|
end
|
63
66
|
|
64
67
|
def issue_details(issue)
|
65
68
|
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."
|
69
|
+
rescue StandardError => e
|
70
|
+
message = "Sorry, but Minitest Heat couldn't display output for a specific failure."
|
68
71
|
exception_guidance(message, e)
|
69
72
|
end
|
70
73
|
|
@@ -75,7 +78,7 @@ module Minitest
|
|
75
78
|
def compact_summary(results, timer)
|
76
79
|
newline
|
77
80
|
print_tokens ::Minitest::Heat::Output::Results.new(results, timer).tokens
|
78
|
-
rescue => e
|
81
|
+
rescue StandardError => e
|
79
82
|
message = "Sorry, but Minitest Heat couldn't display the summary."
|
80
83
|
exception_guidance(message, e)
|
81
84
|
end
|
@@ -84,15 +87,24 @@ module Minitest
|
|
84
87
|
newline
|
85
88
|
print_tokens ::Minitest::Heat::Output::Map.new(map).tokens
|
86
89
|
newline
|
87
|
-
rescue => e
|
90
|
+
rescue StandardError => e
|
88
91
|
message = "Sorry, but Minitest Heat couldn't display the heat map."
|
89
92
|
exception_guidance(message, e)
|
90
93
|
end
|
91
94
|
|
95
|
+
private
|
96
|
+
|
97
|
+
# Displays some guidance related to exceptions generated by Minitest Heat in order to help
|
98
|
+
# people get back on track (and ideally submit issues)
|
99
|
+
# @param message [String] a slightly more specific explanation of which part of minitest-heat
|
100
|
+
# caused the failure
|
101
|
+
# @param exception [Exception] the exception that caused the problem
|
102
|
+
#
|
103
|
+
# @return [void] displays the guidance to the console
|
92
104
|
def exception_guidance(message, exception)
|
93
105
|
newline
|
94
106
|
puts "#{message} Disabling Minitest Heat can get you back on track until the problem can be fixed."
|
95
|
-
puts
|
107
|
+
puts 'Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues'
|
96
108
|
puts "#{exception.message}:"
|
97
109
|
exception.backtrace.each do |line|
|
98
110
|
puts " #{line}"
|
@@ -100,8 +112,6 @@ module Minitest
|
|
100
112
|
newline
|
101
113
|
end
|
102
114
|
|
103
|
-
private
|
104
|
-
|
105
115
|
def no_problems?(results)
|
106
116
|
!results.problems?
|
107
117
|
end
|
@@ -138,7 +148,11 @@ module Minitest
|
|
138
148
|
def print_tokens(lines_of_tokens)
|
139
149
|
lines_of_tokens.each do |tokens|
|
140
150
|
tokens.each do |token|
|
141
|
-
|
151
|
+
begin
|
152
|
+
print Token.new(*token).to_s(token_format)
|
153
|
+
rescue
|
154
|
+
puts token.inspect
|
155
|
+
end
|
142
156
|
end
|
143
157
|
newline
|
144
158
|
end
|
@@ -19,16 +19,21 @@ module Minitest
|
|
19
19
|
# Record everything—even if it's a success
|
20
20
|
@issues.push(issue)
|
21
21
|
|
22
|
-
# If it's not a genuine problem, we're done here
|
23
|
-
|
22
|
+
# If it's not a genuine problem, we're done here...
|
23
|
+
return unless issue.hit?
|
24
|
+
|
25
|
+
# ...otherwise update the heat map
|
26
|
+
update_heat_map(issue)
|
24
27
|
end
|
25
28
|
|
26
29
|
def update_heat_map(issue)
|
27
|
-
#
|
28
|
-
pathname
|
29
|
-
|
30
|
+
# For heat map purposes, only the project backtrace lines are interesting
|
31
|
+
pathname, line_number = issue.locations.project.to_a
|
32
|
+
|
33
|
+
# Backtrace is only relevant for exception-generating issues, not slows, skips, or failures
|
34
|
+
backtrace = issue.error? ? issue.locations.backtrace.project_locations : []
|
30
35
|
|
31
|
-
@heat_map.add(pathname, line_number, issue.type)
|
36
|
+
@heat_map.add(pathname, line_number, issue.type, backtrace: backtrace)
|
32
37
|
end
|
33
38
|
|
34
39
|
def problems?
|
data/lib/minitest/heat/source.rb
CHANGED
data/lib/minitest/heat.rb
CHANGED
data/lib/minitest/heat_plugin.rb
CHANGED
@@ -6,7 +6,7 @@ module Minitest # rubocop:disable Style/Documentation
|
|
6
6
|
def self.plugin_heat_init(options)
|
7
7
|
io = options.fetch(:io, $stdout)
|
8
8
|
|
9
|
-
|
9
|
+
reporter.reporters.reject! do |reporter|
|
10
10
|
# Minitest Heat acts as a unified Progress *and* Summary reporter. Using other reporters of
|
11
11
|
# those types in conjunction with it creates some overly-verbose output
|
12
12
|
reporter.is_a?(ProgressReporter) || reporter.is_a?(SummaryReporter)
|
@@ -74,12 +74,16 @@ module Minitest
|
|
74
74
|
|
75
75
|
# Show the marker
|
76
76
|
output.marker(issue.type)
|
77
|
-
rescue => e
|
77
|
+
rescue StandardError => e
|
78
|
+
display_exception_guidance(e)
|
79
|
+
end
|
80
|
+
|
81
|
+
def display_exception_guidance(exception)
|
78
82
|
output.newline
|
79
|
-
puts
|
80
|
-
puts
|
81
|
-
puts "#{
|
82
|
-
|
83
|
+
puts 'Sorry, but Minitest Heat encountered an exception recording an issue. Disabling Minitest Heat will get you back on track.'
|
84
|
+
puts 'Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues'
|
85
|
+
puts "#{exception.message}:"
|
86
|
+
exception.backtrace.each do |line|
|
83
87
|
puts " #{line}"
|
84
88
|
end
|
85
89
|
output.newline
|
@@ -92,13 +96,16 @@ module Minitest
|
|
92
96
|
# The list of individual issues and their associated details
|
93
97
|
output.issues_list(results)
|
94
98
|
|
95
|
-
# Display a short summary of the total issue counts
|
99
|
+
# Display a short summary of the total issue counts for each category as well as performance
|
96
100
|
# details for the test suite as a whole
|
97
101
|
output.compact_summary(results, timer)
|
98
102
|
|
99
103
|
# If there were issues, shows a short heat map summary of which files and lines were the most
|
100
104
|
# common sources of issues
|
101
105
|
output.heat_map(results)
|
106
|
+
|
107
|
+
output.newline
|
108
|
+
output.newline
|
102
109
|
end
|
103
110
|
|
104
111
|
# Did this run pass?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-heat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garrett Dimon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -141,12 +141,19 @@ files:
|
|
141
141
|
- Rakefile
|
142
142
|
- bin/console
|
143
143
|
- bin/setup
|
144
|
+
- examples/exceptions.png
|
145
|
+
- examples/failures.png
|
146
|
+
- examples/map.png
|
147
|
+
- examples/markers.png
|
148
|
+
- examples/skips.png
|
149
|
+
- examples/slows.png
|
144
150
|
- lib/minitest/heat.rb
|
145
151
|
- lib/minitest/heat/backtrace.rb
|
146
|
-
- lib/minitest/heat/backtrace/
|
152
|
+
- lib/minitest/heat/backtrace/line_parser.rb
|
147
153
|
- lib/minitest/heat/hit.rb
|
148
154
|
- lib/minitest/heat/issue.rb
|
149
155
|
- lib/minitest/heat/location.rb
|
156
|
+
- lib/minitest/heat/locations.rb
|
150
157
|
- lib/minitest/heat/map.rb
|
151
158
|
- lib/minitest/heat/output.rb
|
152
159
|
- lib/minitest/heat/output/backtrace.rb
|
@@ -188,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
195
|
- !ruby/object:Gem::Version
|
189
196
|
version: '0'
|
190
197
|
requirements: []
|
191
|
-
rubygems_version: 3.
|
198
|
+
rubygems_version: 3.2.22
|
192
199
|
signing_key:
|
193
200
|
specification_version: 4
|
194
201
|
summary: Presents test results in a visual manner to guide you to where to look first.
|