minitest-heat 0.0.9 → 0.0.13
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +6 -6
- data/README.md +49 -14
- 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 +39 -43
- data/lib/minitest/heat/hit.rb +36 -19
- data/lib/minitest/heat/issue.rb +118 -81
- data/lib/minitest/heat/location.rb +115 -116
- data/lib/minitest/heat/locations.rb +105 -0
- data/lib/minitest/heat/map.rb +16 -4
- data/lib/minitest/heat/output/backtrace.rb +90 -67
- data/lib/minitest/heat/output/issue.rb +76 -67
- data/lib/minitest/heat/output/map.rb +127 -25
- data/lib/minitest/heat/output/marker.rb +5 -3
- data/lib/minitest/heat/output/results.rb +3 -2
- data/lib/minitest/heat/output/source_code.rb +1 -1
- data/lib/minitest/heat/output/token.rb +2 -1
- data/lib/minitest/heat/output.rb +76 -6
- data/lib/minitest/heat/results.rb +23 -3
- data/lib/minitest/heat/source.rb +1 -1
- data/lib/minitest/heat/version.rb +1 -1
- data/lib/minitest/heat.rb +3 -2
- data/lib/minitest/heat_plugin.rb +9 -17
- data/lib/minitest/heat_reporter.rb +25 -35
- metadata +11 -4
- data/lib/minitest/heat/line.rb +0 -74
@@ -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
|
|
@@ -12,16 +13,36 @@ module Minitest
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def tokens
|
15
|
-
|
16
|
-
|
17
|
-
|
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)
|
18
20
|
|
19
|
-
|
21
|
+
# Add a new line
|
22
|
+
@tokens << [[:muted, ""]]
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
25
46
|
end
|
26
47
|
|
27
48
|
@tokens
|
@@ -29,13 +50,41 @@ module Minitest
|
|
29
50
|
|
30
51
|
private
|
31
52
|
|
32
|
-
def
|
33
|
-
|
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
|
+
]
|
34
81
|
end
|
35
82
|
|
36
83
|
def relevant_issue_types
|
84
|
+
# These are always relevant.
|
37
85
|
issue_types = %i[error broken failure]
|
38
86
|
|
87
|
+
# These are only relevant if there aren't more serious isues.
|
39
88
|
issue_types << :skipped unless results.problems?
|
40
89
|
issue_types << :painful unless results.problems? || results.skips.any?
|
41
90
|
issue_types << :slow unless results.problems? || results.skips.any?
|
@@ -43,32 +92,85 @@ module Minitest
|
|
43
92
|
issue_types
|
44
93
|
end
|
45
94
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
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
|
99
|
+
|
100
|
+
intersection_issue_types.any?
|
101
|
+
end
|
102
|
+
|
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)
|
111
|
+
end
|
112
|
+
|
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
|
49
119
|
|
50
120
|
[
|
51
|
-
[:default, directory],
|
121
|
+
[:default, "#{directory}/"],
|
52
122
|
[:bold, filename],
|
53
123
|
[:default, ' · ']
|
54
124
|
]
|
55
125
|
end
|
56
126
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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)
|
133
|
+
line_number_tokens = []
|
134
|
+
|
135
|
+
relevant_issue_types.each do |issue_type|
|
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
|
62
143
|
end
|
63
|
-
|
144
|
+
|
145
|
+
line_number_tokens.compact
|
64
146
|
end
|
65
147
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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)
|
166
|
+
# Sort the collected group of line number hits so they're in order
|
167
|
+
line_number_tokens_for_hit(hit).sort do |a, b|
|
168
|
+
# Ensure the line numbers are integers for sorting (otherwise '100' comes before '12')
|
169
|
+
first_line_number = Integer(a[1].strip)
|
170
|
+
second_line_number = Integer(b[1].strip)
|
171
|
+
|
172
|
+
first_line_number <=> second_line_number
|
70
173
|
end
|
71
|
-
line_number_tokens.compact.sort_by { |number_token| number_token[1] }
|
72
174
|
end
|
73
175
|
end
|
74
176
|
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,
|
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,
|
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
|
-
#
|
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
|
|
data/lib/minitest/heat/output.rb
CHANGED
@@ -11,18 +11,18 @@ 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: '➜',
|
18
|
-
lead: '|'
|
18
|
+
lead: '|'
|
19
19
|
}.freeze
|
20
20
|
|
21
21
|
TOKENS = {
|
22
|
-
spacer:
|
22
|
+
spacer: [:muted, " #{SYMBOLS[:middot]} "],
|
23
23
|
muted_arrow: [:muted, " #{SYMBOLS[:arrow]} "],
|
24
|
-
muted_lead:
|
25
|
-
}
|
24
|
+
muted_lead: [:muted, "#{SYMBOLS[:lead]} "]
|
25
|
+
}.freeze
|
26
26
|
|
27
27
|
attr_reader :stream
|
28
28
|
|
@@ -42,8 +42,33 @@ 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
|
+
#
|
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.
|
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.
|
58
|
+
next unless show?(issue_category, results)
|
59
|
+
|
60
|
+
results.send(issue_category).each { |issue| issue_details(issue) }
|
61
|
+
end
|
62
|
+
rescue StandardError => e
|
63
|
+
message = "Sorry, but Minitest Heat couldn't display the details of any failures."
|
64
|
+
exception_guidance(message, e)
|
65
|
+
end
|
66
|
+
|
45
67
|
def issue_details(issue)
|
46
68
|
print_tokens Minitest::Heat::Output::Issue.new(issue).tokens
|
69
|
+
rescue StandardError => e
|
70
|
+
message = "Sorry, but Minitest Heat couldn't display output for a specific failure."
|
71
|
+
exception_guidance(message, e)
|
47
72
|
end
|
48
73
|
|
49
74
|
def marker(issue_type)
|
@@ -53,15 +78,56 @@ module Minitest
|
|
53
78
|
def compact_summary(results, timer)
|
54
79
|
newline
|
55
80
|
print_tokens ::Minitest::Heat::Output::Results.new(results, timer).tokens
|
81
|
+
rescue StandardError => e
|
82
|
+
message = "Sorry, but Minitest Heat couldn't display the summary."
|
83
|
+
exception_guidance(message, e)
|
56
84
|
end
|
57
85
|
|
58
86
|
def heat_map(map)
|
59
87
|
newline
|
60
88
|
print_tokens ::Minitest::Heat::Output::Map.new(map).tokens
|
89
|
+
newline
|
90
|
+
rescue StandardError => e
|
91
|
+
message = "Sorry, but Minitest Heat couldn't display the heat map."
|
92
|
+
exception_guidance(message, e)
|
61
93
|
end
|
62
94
|
|
63
95
|
private
|
64
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
|
104
|
+
def exception_guidance(message, exception)
|
105
|
+
newline
|
106
|
+
puts "#{message} Disabling Minitest Heat can get you back on track until the problem can be fixed."
|
107
|
+
puts 'Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues'
|
108
|
+
puts "#{exception.message}:"
|
109
|
+
exception.backtrace.each do |line|
|
110
|
+
puts " #{line}"
|
111
|
+
end
|
112
|
+
newline
|
113
|
+
end
|
114
|
+
|
115
|
+
def no_problems?(results)
|
116
|
+
!results.problems?
|
117
|
+
end
|
118
|
+
|
119
|
+
def no_problems_or_skips?(results)
|
120
|
+
!results.problems? && results.skips.none?
|
121
|
+
end
|
122
|
+
|
123
|
+
def show?(issue_category, results)
|
124
|
+
case issue_category
|
125
|
+
when :skips then no_problems?(results)
|
126
|
+
when :painfuls, :slows then no_problems_or_skips?(results)
|
127
|
+
else true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
65
131
|
def style_enabled?
|
66
132
|
stream.tty?
|
67
133
|
end
|
@@ -82,7 +148,11 @@ module Minitest
|
|
82
148
|
def print_tokens(lines_of_tokens)
|
83
149
|
lines_of_tokens.each do |tokens|
|
84
150
|
tokens.each do |token|
|
85
|
-
|
151
|
+
begin
|
152
|
+
print Token.new(*token).to_s(token_format)
|
153
|
+
rescue
|
154
|
+
puts token.inspect
|
155
|
+
end
|
86
156
|
end
|
87
157
|
newline
|
88
158
|
end
|
@@ -11,9 +11,29 @@ 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
|
-
|
21
|
+
|
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)
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_heat_map(issue)
|
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 : []
|
35
|
+
|
36
|
+
@heat_map.add(pathname, line_number, issue.type, backtrace: backtrace)
|
17
37
|
end
|
18
38
|
|
19
39
|
def problems?
|
@@ -37,11 +57,11 @@ module Minitest
|
|
37
57
|
end
|
38
58
|
|
39
59
|
def painfuls
|
40
|
-
@painfuls ||= select_issues(:painful).sort_by(&:
|
60
|
+
@painfuls ||= select_issues(:painful).sort_by(&:execution_time).reverse
|
41
61
|
end
|
42
62
|
|
43
63
|
def slows
|
44
|
-
@slows ||= select_issues(:slow).sort_by(&:
|
64
|
+
@slows ||= select_issues(:slow).sort_by(&:execution_time).reverse
|
45
65
|
end
|
46
66
|
|
47
67
|
private
|
data/lib/minitest/heat/source.rb
CHANGED
data/lib/minitest/heat.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
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'
|
7
|
+
require_relative 'heat/locations'
|
8
8
|
require_relative 'heat/map'
|
9
9
|
require_relative 'heat/output'
|
10
10
|
require_relative 'heat/results'
|
@@ -13,7 +13,8 @@ require_relative 'heat/timer'
|
|
13
13
|
require_relative 'heat/version'
|
14
14
|
|
15
15
|
module Minitest
|
16
|
-
# Custom
|
16
|
+
# Custom Minitest reporter focused on generating output designed around efficiently identifying
|
17
|
+
# issues and potential solutions
|
17
18
|
# - Colorize the Output
|
18
19
|
# - What files had the most errors?
|
19
20
|
# - Show the most impacted areas first.
|
data/lib/minitest/heat_plugin.rb
CHANGED
@@ -2,25 +2,17 @@
|
|
2
2
|
|
3
3
|
require_relative 'heat_reporter'
|
4
4
|
|
5
|
-
module Minitest
|
6
|
-
def self.plugin_heat_options(opts, _options)
|
7
|
-
opts.on '--show-fast', 'Show failures as they happen instead of waiting for the entire suite.' do
|
8
|
-
# Heat.show_fast!
|
9
|
-
end
|
10
|
-
|
11
|
-
# TODO: options.
|
12
|
-
# 1. Fail Fast
|
13
|
-
# 2. Don't worry about skips.
|
14
|
-
# 3. Skip coverage.
|
15
|
-
end
|
16
|
-
|
5
|
+
module Minitest # rubocop:disable Style/Documentation
|
17
6
|
def self.plugin_heat_init(options)
|
18
|
-
io = options
|
7
|
+
io = options.fetch(:io, $stdout)
|
19
8
|
|
20
|
-
|
21
|
-
|
9
|
+
reporter.reporters.reject! do |reporter|
|
10
|
+
# Minitest Heat acts as a unified Progress *and* Summary reporter. Using other reporters of
|
11
|
+
# those types in conjunction with it creates some overly-verbose output
|
12
|
+
reporter.is_a?(ProgressReporter) || reporter.is_a?(SummaryReporter)
|
13
|
+
end
|
22
14
|
|
23
|
-
#
|
24
|
-
reporter << HeatReporter.new(io, options)
|
15
|
+
# Hook up Reviewer
|
16
|
+
self.reporter.reporters << HeatReporter.new(io, options)
|
25
17
|
end
|
26
18
|
end
|
@@ -35,6 +35,8 @@ module Minitest
|
|
35
35
|
:results
|
36
36
|
|
37
37
|
def initialize(io = $stdout, options = {})
|
38
|
+
super()
|
39
|
+
|
38
40
|
@options = options
|
39
41
|
|
40
42
|
@timer = Heat::Timer.new
|
@@ -62,33 +64,39 @@ module Minitest
|
|
62
64
|
def record(result)
|
63
65
|
# Convert a Minitest Result into an "issue" to more consistently expose the data needed to
|
64
66
|
# adjust the failure output to the type of failure
|
65
|
-
issue = Heat::Issue.
|
67
|
+
issue = Heat::Issue.from_result(result)
|
68
|
+
|
69
|
+
# Note the number of assertions for the performance summary
|
70
|
+
timer.increment_counts(issue.assertions)
|
66
71
|
|
67
|
-
|
72
|
+
# Record the issue to show details later
|
68
73
|
results.record(issue)
|
69
74
|
|
75
|
+
# Show the marker
|
70
76
|
output.marker(issue.type)
|
77
|
+
rescue StandardError => e
|
78
|
+
display_exception_guidance(e)
|
71
79
|
end
|
72
80
|
|
73
|
-
|
74
|
-
def report
|
75
|
-
timer.stop!
|
76
|
-
|
77
|
-
# A couple of blank lines to create some breathing room
|
81
|
+
def display_exception_guidance(exception)
|
78
82
|
output.newline
|
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|
|
87
|
+
puts " #{line}"
|
88
|
+
end
|
79
89
|
output.newline
|
90
|
+
end
|
80
91
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# issues will be displayed without scrolling once more problematic issues are resolved.
|
85
|
-
%i[slows painfuls skips failures brokens errors].each do |issue_category|
|
86
|
-
next unless show?(issue_category)
|
92
|
+
# Outputs the summary of the run.
|
93
|
+
def report
|
94
|
+
timer.stop!
|
87
95
|
|
88
|
-
|
89
|
-
|
96
|
+
# The list of individual issues and their associated details
|
97
|
+
output.issues_list(results)
|
90
98
|
|
91
|
-
# 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
|
92
100
|
# details for the test suite as a whole
|
93
101
|
output.compact_summary(results, timer)
|
94
102
|
|
@@ -96,7 +104,7 @@ module Minitest
|
|
96
104
|
# common sources of issues
|
97
105
|
output.heat_map(results)
|
98
106
|
|
99
|
-
|
107
|
+
output.newline
|
100
108
|
output.newline
|
101
109
|
end
|
102
110
|
|
@@ -104,23 +112,5 @@ module Minitest
|
|
104
112
|
def passed?
|
105
113
|
results.errors.empty? && results.failures.empty?
|
106
114
|
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
def no_problems?
|
111
|
-
!results.problems?
|
112
|
-
end
|
113
|
-
|
114
|
-
def no_problems_or_skips?
|
115
|
-
!results.problems? && !results.skips.any?
|
116
|
-
end
|
117
|
-
|
118
|
-
def show?(issue_category)
|
119
|
-
case issue_category
|
120
|
-
when :skips then no_problems?
|
121
|
-
when :painfuls, :slows then no_problems_or_skips?
|
122
|
-
else true
|
123
|
-
end
|
124
|
-
end
|
125
115
|
end
|
126
116
|
end
|
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.13
|
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
|
152
|
+
- lib/minitest/heat/backtrace/line_parser.rb
|
146
153
|
- lib/minitest/heat/hit.rb
|
147
154
|
- lib/minitest/heat/issue.rb
|
148
|
-
- lib/minitest/heat/line.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.
|