minitest-heat 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/minitest/heat/issue.rb +2 -2
- data/lib/minitest/heat/output/backtrace.rb +6 -6
- data/lib/minitest/heat/output/issue.rb +73 -22
- data/lib/minitest/heat/output/results.rb +31 -21
- data/lib/minitest/heat/output.rb +14 -2
- data/lib/minitest/heat/results.rb +14 -85
- data/lib/minitest/heat/timer.rb +81 -0
- data/lib/minitest/heat/version.rb +1 -1
- data/lib/minitest/heat.rb +1 -0
- data/lib/minitest/heat_reporter.rb +29 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e33245f206aa23bcbad541459db13fb8f6f088df51777850bb1276369dc0b3b
|
4
|
+
data.tar.gz: f66fd4f6ba49d1f80be0f97e0d54fd5fa5a2f4fa2063a57f20d9f46520d17ed2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24897c2218d77cae17eba80b0e28f24df8f051d13f3f2cddeb47ffabb4730a19b45601f34119749f7fa3d7828fbe617313821d6939cf41653e6559e91bf74526
|
7
|
+
data.tar.gz: 38b9e2b060ba864243e384ef260bfb9f771b607bc2786668d462abee84142d5505f3de63182e8238e94bc8ba01932f991125a4db1fcceb4252d764afcc7a62f8
|
data/Gemfile.lock
CHANGED
data/lib/minitest/heat/issue.rb
CHANGED
@@ -20,7 +20,7 @@ module Minitest
|
|
20
20
|
attr_reader :result, :location, :failure
|
21
21
|
|
22
22
|
def_delegators :@result, :passed?, :error?, :skipped?
|
23
|
-
def_delegators :@location, :backtrace
|
23
|
+
def_delegators :@location, :backtrace, :test_definition_line, :test_failure_line
|
24
24
|
|
25
25
|
def initialize(result)
|
26
26
|
@result = result
|
@@ -34,7 +34,7 @@ module Minitest
|
|
34
34
|
#
|
35
35
|
# @return [String] the pathname for the file relative to the present working directory
|
36
36
|
def short_location
|
37
|
-
location.to_s.delete_prefix(Dir.pwd)
|
37
|
+
location.to_s.delete_prefix("#{Dir.pwd}/")
|
38
38
|
end
|
39
39
|
|
40
40
|
# Converts an issue to the key attributes for recording a 'hit'
|
@@ -26,7 +26,7 @@ module Minitest
|
|
26
26
|
parts = [
|
27
27
|
indentation_token,
|
28
28
|
path_token(backtrace_entry),
|
29
|
-
|
29
|
+
*file_and_line_number_tokens(backtrace_entry),
|
30
30
|
source_code_line_token(backtrace_entry.source_code)
|
31
31
|
]
|
32
32
|
|
@@ -52,7 +52,7 @@ module Minitest
|
|
52
52
|
# ...it's smart about exceptions that were raised outside of the project?
|
53
53
|
# ...it's smart about highlighting lines of code differently based on whether it's source code, test code, or external code?
|
54
54
|
def backtrace_entries
|
55
|
-
|
55
|
+
all_entries
|
56
56
|
end
|
57
57
|
|
58
58
|
private
|
@@ -92,16 +92,16 @@ module Minitest
|
|
92
92
|
[:muted, path]
|
93
93
|
end
|
94
94
|
|
95
|
-
def
|
96
|
-
[:default,
|
95
|
+
def file_and_line_number_tokens(backtrace_entry)
|
96
|
+
[[:default, backtrace_entry.file], [:muted, ':'], [:default, backtrace_entry.line_number]]
|
97
97
|
end
|
98
98
|
|
99
99
|
def source_code_line_token(source_code)
|
100
|
-
[:muted, " `#{source_code.line.strip}`"]
|
100
|
+
[:muted, " #{Output::SYMBOLS[:arrow]} `#{source_code.line.strip}`"]
|
101
101
|
end
|
102
102
|
|
103
103
|
def file_freshness(_line)
|
104
|
-
[:
|
104
|
+
[:default, " #{Output::SYMBOLS[:middot]} Most Recently Modified File"]
|
105
105
|
end
|
106
106
|
|
107
107
|
# The number of spaces each line of code should be indented. Currently defaults to 2 in
|
@@ -4,11 +4,6 @@ module Minitest
|
|
4
4
|
module Heat
|
5
5
|
class Output
|
6
6
|
class Issue
|
7
|
-
SHARED_SYMBOLS = {
|
8
|
-
spacer: ' · ',
|
9
|
-
arrow: ' > '
|
10
|
-
}.freeze
|
11
|
-
|
12
7
|
attr_accessor :issue
|
13
8
|
|
14
9
|
def initialize(issue)
|
@@ -31,6 +26,8 @@ module Minitest
|
|
31
26
|
def error_tokens
|
32
27
|
[
|
33
28
|
headline_tokens,
|
29
|
+
test_location_tokens,
|
30
|
+
location_tokens,
|
34
31
|
summary_tokens,
|
35
32
|
*backtrace_tokens,
|
36
33
|
newline_tokens
|
@@ -40,6 +37,7 @@ module Minitest
|
|
40
37
|
def broken_tokens
|
41
38
|
[
|
42
39
|
headline_tokens,
|
40
|
+
test_location_tokens,
|
43
41
|
summary_tokens,
|
44
42
|
*backtrace_tokens,
|
45
43
|
newline_tokens
|
@@ -49,9 +47,8 @@ module Minitest
|
|
49
47
|
def failure_tokens
|
50
48
|
[
|
51
49
|
headline_tokens,
|
50
|
+
test_location_tokens,
|
52
51
|
summary_tokens,
|
53
|
-
location_tokens,
|
54
|
-
*source_tokens,
|
55
52
|
newline_tokens
|
56
53
|
]
|
57
54
|
end
|
@@ -59,7 +56,7 @@ module Minitest
|
|
59
56
|
def skipped_tokens
|
60
57
|
[
|
61
58
|
headline_tokens,
|
62
|
-
|
59
|
+
test_location_tokens,
|
63
60
|
newline_tokens
|
64
61
|
]
|
65
62
|
end
|
@@ -67,7 +64,7 @@ module Minitest
|
|
67
64
|
def painful_tokens
|
68
65
|
[
|
69
66
|
headline_tokens,
|
70
|
-
|
67
|
+
slowness_summary_tokens,
|
71
68
|
newline_tokens
|
72
69
|
]
|
73
70
|
end
|
@@ -75,17 +72,17 @@ module Minitest
|
|
75
72
|
def slow_tokens
|
76
73
|
[
|
77
74
|
headline_tokens,
|
78
|
-
|
75
|
+
slowness_summary_tokens,
|
79
76
|
newline_tokens
|
80
77
|
]
|
81
78
|
end
|
82
79
|
|
83
80
|
def headline_tokens
|
84
|
-
[[issue.type, issue.label],
|
81
|
+
[[issue.type, issue.label], spacer_token, [:default, issue.test_name]]
|
85
82
|
end
|
86
83
|
|
87
|
-
def
|
88
|
-
[[:
|
84
|
+
def test_name_and_class_tokens
|
85
|
+
[[:default, issue.test_class], *test_location_tokens ]
|
89
86
|
end
|
90
87
|
|
91
88
|
def backtrace_tokens
|
@@ -94,34 +91,88 @@ module Minitest
|
|
94
91
|
backtrace.tokens
|
95
92
|
end
|
96
93
|
|
94
|
+
def test_location_tokens
|
95
|
+
[[:default, test_file_short_location], [:muted, ':'], [:default, issue.test_definition_line], arrow_token, [:default, issue.test_failure_line], [:muted, test_line_source]]
|
96
|
+
end
|
97
|
+
|
97
98
|
def location_tokens
|
98
|
-
[[:muted, issue.
|
99
|
+
[[:default, most_relevant_short_location], [:muted, ':'], [:default, issue.location.most_relevant_failure_line], [:muted, most_relevant_line_source]]
|
99
100
|
end
|
100
101
|
|
101
102
|
def source_tokens
|
102
103
|
filename = issue.location.project_file
|
103
104
|
line_number = issue.location.project_failure_line
|
104
105
|
|
105
|
-
source_code = ::Minitest::Heat::Output::SourceCode.new(filename, line_number)
|
106
|
+
# source_code = ::Minitest::Heat::Output::SourceCode.new(filename, line_number, max_line_count: 1)
|
107
|
+
# source_code.tokens
|
106
108
|
|
107
|
-
|
109
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
110
|
+
[[:muted, " #{Output::SYMBOLS[:arrow]} `#{source.line.strip}`"]]
|
108
111
|
end
|
109
112
|
|
110
|
-
def
|
111
|
-
[[:
|
113
|
+
def summary_tokens
|
114
|
+
[[:italicized, issue.summary.delete_suffix("---------------")]]
|
115
|
+
end
|
116
|
+
|
117
|
+
def slowness_summary_tokens
|
118
|
+
[[:bold, issue.slowness], spacer_token, [:default, issue.short_location]]
|
112
119
|
end
|
113
120
|
|
114
121
|
def newline_tokens
|
115
122
|
[]
|
116
123
|
end
|
117
124
|
|
118
|
-
def
|
119
|
-
|
125
|
+
def most_relevant_short_location
|
126
|
+
issue.location.most_relevant_file.to_s.delete_prefix("#{Dir.pwd}/")
|
120
127
|
end
|
121
128
|
|
122
|
-
def
|
123
|
-
|
129
|
+
def test_file_short_location
|
130
|
+
issue.location.test_file.to_s.delete_prefix("#{Dir.pwd}/")
|
124
131
|
end
|
132
|
+
|
133
|
+
def most_relevant_line_source
|
134
|
+
filename = issue.location.project_file
|
135
|
+
line_number = issue.location.project_failure_line
|
136
|
+
|
137
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
138
|
+
"\n #{source.line.strip}"
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_line_source
|
142
|
+
filename = issue.location.test_file
|
143
|
+
line_number = issue.location.test_failure_line
|
144
|
+
|
145
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
146
|
+
"\n #{source.line.strip}"
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
# def failure_summary_tokens
|
151
|
+
# return unless issue_summary_lines.any?
|
152
|
+
|
153
|
+
# # Sometimes, the exception message is multiple lines, so this adjusts the lines to
|
154
|
+
# # visually group them together a bit
|
155
|
+
# if issue_summary_lines.one?
|
156
|
+
# [[[:italicized, issue_summary_lines.first]]]
|
157
|
+
# else
|
158
|
+
# issue_summary_lines.map do |line|
|
159
|
+
# [Output::TOKENS[:muted_lead], [:italicized, line]]
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
# end
|
163
|
+
|
164
|
+
# def issue_summary_lines
|
165
|
+
# @issue_summary_lines ||= issue.summary.split("\n")
|
166
|
+
# end
|
167
|
+
|
168
|
+
def spacer_token
|
169
|
+
Output::TOKENS[:spacer]
|
170
|
+
end
|
171
|
+
|
172
|
+
def arrow_token
|
173
|
+
Output::TOKENS[:muted_arrow]
|
174
|
+
end
|
175
|
+
|
125
176
|
end
|
126
177
|
end
|
127
178
|
end
|
@@ -6,19 +6,25 @@ module Minitest
|
|
6
6
|
class Results
|
7
7
|
extend Forwardable
|
8
8
|
|
9
|
-
attr_accessor :results
|
9
|
+
attr_accessor :results, :timer
|
10
10
|
|
11
|
-
def_delegators :@results, :errors, :brokens, :failures, :skips, :painfuls, :slows, :problems
|
11
|
+
def_delegators :@results, :issues, :errors, :brokens, :failures, :skips, :painfuls, :slows, :problems?
|
12
12
|
|
13
|
-
def initialize(results)
|
13
|
+
def initialize(results, timer)
|
14
14
|
@results = results
|
15
|
+
@timer = timer
|
15
16
|
@tokens = []
|
16
17
|
end
|
17
18
|
|
18
19
|
def tokens
|
20
|
+
# Only show the issue type counts if there are issues
|
19
21
|
@tokens << [*issue_counts_tokens] if issue_counts_tokens&.any?
|
20
|
-
|
21
|
-
@tokens << [
|
22
|
+
|
23
|
+
@tokens << [
|
24
|
+
timing_token, spacer_token,
|
25
|
+
test_count_token, tests_performance_token, join_token,
|
26
|
+
assertions_count_token, assertions_performance_token
|
27
|
+
]
|
22
28
|
|
23
29
|
@tokens
|
24
30
|
end
|
@@ -33,7 +39,7 @@ module Minitest
|
|
33
39
|
end
|
34
40
|
|
35
41
|
def issue_counts_tokens
|
36
|
-
return unless
|
42
|
+
return unless issues.any?
|
37
43
|
|
38
44
|
counts = [
|
39
45
|
error_count_token,
|
@@ -45,10 +51,10 @@ module Minitest
|
|
45
51
|
].compact
|
46
52
|
|
47
53
|
# # Create an array of separator tokens one less than the total number of issue count tokens
|
48
|
-
|
54
|
+
spacer_tokens = Array.new(counts.size, spacer_token)
|
49
55
|
|
50
56
|
counts_with_separators = counts
|
51
|
-
.zip(
|
57
|
+
.zip(spacer_tokens) # Add separators between the counts
|
52
58
|
.flatten(1) # Flatten the zipped separators, but no more
|
53
59
|
|
54
60
|
counts_with_separators.pop # Remove the final trailing zipped separator that's not needed
|
@@ -74,33 +80,33 @@ module Minitest
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def painful_count_token
|
77
|
-
style = problems? ? :muted : :painful
|
83
|
+
style = problems? || skips.any? ? :muted : :painful
|
78
84
|
issue_count_token(style, painfuls, name: 'Painfully Slow')
|
79
85
|
end
|
80
86
|
|
81
87
|
def slow_count_token
|
82
|
-
style = problems? ? :muted : :slow
|
88
|
+
style = problems? || skips.any? ? :muted : :slow
|
83
89
|
issue_count_token(style, slows, name: 'Slow')
|
84
90
|
end
|
85
91
|
|
86
|
-
def
|
87
|
-
[:
|
92
|
+
def test_count_token
|
93
|
+
[:default, "#{pluralize(timer.test_count, 'test')}"]
|
88
94
|
end
|
89
95
|
|
90
96
|
def tests_performance_token
|
91
|
-
[:default, "
|
97
|
+
[:default, " (#{timer.tests_per_second}/s)"]
|
92
98
|
end
|
93
99
|
|
94
|
-
def
|
95
|
-
[:default, "
|
100
|
+
def assertions_count_token
|
101
|
+
[:default, "#{pluralize(timer.assertion_count, 'assertion')}"]
|
96
102
|
end
|
97
103
|
|
98
|
-
def
|
99
|
-
[:
|
104
|
+
def assertions_performance_token
|
105
|
+
[:default, " (#{timer.assertions_per_second}/s)"]
|
100
106
|
end
|
101
107
|
|
102
|
-
def
|
103
|
-
[:
|
108
|
+
def timing_token
|
109
|
+
[:bold, "#{timer.total_time.round(2)}s"]
|
104
110
|
end
|
105
111
|
|
106
112
|
def issue_count_token(type, collection, name: type.capitalize)
|
@@ -109,8 +115,12 @@ module Minitest
|
|
109
115
|
[type, pluralize(collection.size, name)]
|
110
116
|
end
|
111
117
|
|
112
|
-
def
|
113
|
-
[:
|
118
|
+
def spacer_token
|
119
|
+
Output::TOKENS[:spacer]
|
120
|
+
end
|
121
|
+
|
122
|
+
def join_token
|
123
|
+
[:default, ' with ']
|
114
124
|
end
|
115
125
|
end
|
116
126
|
end
|
data/lib/minitest/heat/output.rb
CHANGED
@@ -12,6 +12,18 @@ module Minitest
|
|
12
12
|
module Heat
|
13
13
|
# Friendly API for printing nicely-formatted output to the console
|
14
14
|
class Output
|
15
|
+
SYMBOLS = {
|
16
|
+
middot: '·',
|
17
|
+
arrow: '➜',
|
18
|
+
lead: '|',
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
TOKENS = {
|
22
|
+
spacer: [:muted, " #{SYMBOLS[:middot]} "],
|
23
|
+
muted_arrow: [:muted, " #{SYMBOLS[:arrow]} "],
|
24
|
+
muted_lead: [:muted, "#{SYMBOLS[:lead]} "],
|
25
|
+
}
|
26
|
+
|
15
27
|
attr_reader :stream
|
16
28
|
|
17
29
|
def initialize(stream = $stdout)
|
@@ -38,9 +50,9 @@ module Minitest
|
|
38
50
|
print_token Minitest::Heat::Output::Marker.new(issue_type).token
|
39
51
|
end
|
40
52
|
|
41
|
-
def compact_summary(results)
|
53
|
+
def compact_summary(results, timer)
|
42
54
|
newline
|
43
|
-
print_tokens ::Minitest::Heat::Output::Results.new(results).tokens
|
55
|
+
print_tokens ::Minitest::Heat::Output::Results.new(results, timer).tokens
|
44
56
|
end
|
45
57
|
|
46
58
|
def heat_map(map)
|
@@ -4,119 +4,48 @@ module Minitest
|
|
4
4
|
module Heat
|
5
5
|
# A collection of test failures
|
6
6
|
class Results
|
7
|
-
attr_reader :
|
8
|
-
:assertion_count,
|
9
|
-
:success_count,
|
10
|
-
:issues,
|
11
|
-
:start_time,
|
12
|
-
:stop_time
|
7
|
+
attr_reader :issues
|
13
8
|
|
14
9
|
def initialize
|
15
|
-
@
|
16
|
-
@assertion_count = 0
|
17
|
-
@success_count = 0
|
18
|
-
@issues = {
|
19
|
-
error: [],
|
20
|
-
broken: [],
|
21
|
-
failure: [],
|
22
|
-
skipped: [],
|
23
|
-
painful: [],
|
24
|
-
slow: []
|
25
|
-
}
|
26
|
-
@start_time = nil
|
27
|
-
@stop_time = nil
|
10
|
+
@issues = []
|
28
11
|
end
|
29
12
|
|
30
|
-
def
|
31
|
-
@
|
32
|
-
end
|
33
|
-
|
34
|
-
def stop_timer!
|
35
|
-
@stop_time = Minitest.clock_time
|
36
|
-
end
|
37
|
-
|
38
|
-
def total_time
|
39
|
-
delta = @stop_time - @start_time
|
40
|
-
|
41
|
-
# Don't return 0
|
42
|
-
delta.zero? ? 0.1 : delta
|
43
|
-
end
|
44
|
-
|
45
|
-
def tests_per_second
|
46
|
-
(assertion_count / total_time).round(2)
|
47
|
-
end
|
48
|
-
|
49
|
-
def assertions_per_second
|
50
|
-
(assertion_count / total_time).round(2)
|
13
|
+
def record(issue)
|
14
|
+
@issues << issue
|
51
15
|
end
|
52
16
|
|
53
17
|
def problems?
|
54
|
-
errors? || brokens? || failures?
|
18
|
+
errors.any? || brokens.any? || failures.any?
|
55
19
|
end
|
56
20
|
|
57
21
|
def errors
|
58
|
-
|
22
|
+
@errors ||= select_issues(:error)
|
59
23
|
end
|
60
24
|
|
61
25
|
def brokens
|
62
|
-
|
26
|
+
@brokens ||= select_issues(:broken)
|
63
27
|
end
|
64
28
|
|
65
29
|
def failures
|
66
|
-
|
30
|
+
@failures ||= select_issues(:failure)
|
67
31
|
end
|
68
32
|
|
69
33
|
def skips
|
70
|
-
|
34
|
+
@skips ||= select_issues(:skipped)
|
71
35
|
end
|
72
36
|
|
73
37
|
def painfuls
|
74
|
-
|
75
|
-
.fetch(:painful) { [] }
|
76
|
-
.sort_by(&:time)
|
77
|
-
.reverse
|
78
|
-
.take(5)
|
38
|
+
@painfuls ||= select_issues(:painful).sort_by(&:time).reverse
|
79
39
|
end
|
80
40
|
|
81
41
|
def slows
|
82
|
-
|
83
|
-
.fetch(:slow) { [] }
|
84
|
-
.sort_by(&:time)
|
85
|
-
.reverse
|
86
|
-
.take(5)
|
87
|
-
end
|
88
|
-
|
89
|
-
def errors?
|
90
|
-
errors.any?
|
42
|
+
@slows ||= select_issues(:slow).sort_by(&:time).reverse
|
91
43
|
end
|
92
44
|
|
93
|
-
|
94
|
-
brokens.any?
|
95
|
-
end
|
96
|
-
|
97
|
-
def failures?
|
98
|
-
failures.any?
|
99
|
-
end
|
100
|
-
|
101
|
-
def skips?
|
102
|
-
skips.any?
|
103
|
-
end
|
104
|
-
|
105
|
-
def painfuls?
|
106
|
-
painfuls.any?
|
107
|
-
end
|
108
|
-
|
109
|
-
def slows?
|
110
|
-
slows.any?
|
111
|
-
end
|
112
|
-
|
113
|
-
def record(issue)
|
114
|
-
@test_count += 1
|
115
|
-
@assertion_count += issue.result.assertions
|
116
|
-
@success_count += 1 if issue.result.passed?
|
45
|
+
private
|
117
46
|
|
118
|
-
|
119
|
-
|
47
|
+
def select_issues(issue_type)
|
48
|
+
issues.select { |issue| issue.type == issue_type }
|
120
49
|
end
|
121
50
|
end
|
122
51
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
module Heat
|
5
|
+
# Provides a timer to keep track of the full test suite duration and provide convenient methods
|
6
|
+
# for calculating tests/second and assertions/second
|
7
|
+
class Timer
|
8
|
+
attr_reader :test_count, :assertion_count, :start_time, :stop_time
|
9
|
+
|
10
|
+
# Creates an instance of a timer to be used for the duration of a test suite run
|
11
|
+
#
|
12
|
+
# @return [self]
|
13
|
+
def initialize
|
14
|
+
@test_count = 0
|
15
|
+
@assertion_count = 0
|
16
|
+
|
17
|
+
@start_time = nil
|
18
|
+
@stop_time = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Records the start time for the full test suite using `Minitest.clock_time`
|
22
|
+
#
|
23
|
+
# @return [Float] the Minitest.clock_time
|
24
|
+
def start!
|
25
|
+
@start_time = Minitest.clock_time
|
26
|
+
end
|
27
|
+
|
28
|
+
# Records the stop time for the full test suite using `Minitest.clock_time`
|
29
|
+
#
|
30
|
+
# @return [Float] the Minitest.clock_time
|
31
|
+
def stop!
|
32
|
+
@stop_time = Minitest.clock_time
|
33
|
+
end
|
34
|
+
|
35
|
+
# Calculates the total time take for the full test suite to run while ensuring it never
|
36
|
+
# returns a zero that would be problematic as a denomitor in calculating average times
|
37
|
+
#
|
38
|
+
# @return [Float] the clocktime duration of the test suite run in seconds
|
39
|
+
def total_time
|
40
|
+
# Don't return 0. The time can end up being 0 for a new or realy fast test suite, and
|
41
|
+
# dividing by 0 doesn't go well when determining average time, so this ensures it uses a
|
42
|
+
# close-enough-but-not-zero value.
|
43
|
+
delta.zero? ? 0.01 : delta
|
44
|
+
end
|
45
|
+
|
46
|
+
# Records the test and assertion counts for a given test outcome
|
47
|
+
# @param count [Integer] the number of assertions from the test
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
def increment_counts(count)
|
51
|
+
@test_count += 1
|
52
|
+
@assertion_count += count
|
53
|
+
end
|
54
|
+
|
55
|
+
# Provides a nice rounded answer for about how many tests were completed per second
|
56
|
+
#
|
57
|
+
# @return [Float] the average number of tests completed per second
|
58
|
+
def tests_per_second
|
59
|
+
(test_count / total_time).round(2)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Provides a nice rounded answer for about how many assertions were completed per second
|
63
|
+
#
|
64
|
+
# @return [Float] the average number of assertions completed per second
|
65
|
+
def assertions_per_second
|
66
|
+
(assertion_count / total_time).round(2)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# The total time the test suite was running.
|
72
|
+
#
|
73
|
+
# @return [Float] the time in seconds elapsed between starting the timer and stopping it
|
74
|
+
def delta
|
75
|
+
return 0 unless start_time && stop_time
|
76
|
+
|
77
|
+
stop_time - start_time
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/minitest/heat.rb
CHANGED
@@ -31,12 +31,14 @@ module Minitest
|
|
31
31
|
class HeatReporter < AbstractReporter
|
32
32
|
attr_reader :output,
|
33
33
|
:options,
|
34
|
+
:timer,
|
34
35
|
:results,
|
35
36
|
:map
|
36
37
|
|
37
38
|
def initialize(io = $stdout, options = {})
|
38
39
|
@options = options
|
39
40
|
|
41
|
+
@timer = Heat::Timer.new
|
40
42
|
@results = Heat::Results.new
|
41
43
|
@map = Heat::Map.new
|
42
44
|
@output = Heat::Output.new(io)
|
@@ -44,7 +46,7 @@ module Minitest
|
|
44
46
|
|
45
47
|
# Starts reporting on the run.
|
46
48
|
def start
|
47
|
-
|
49
|
+
timer.start!
|
48
50
|
|
49
51
|
# A couple of blank lines to create some breathing room
|
50
52
|
output.newline
|
@@ -56,11 +58,15 @@ module Minitest
|
|
56
58
|
def prerecord(klass, name); end
|
57
59
|
|
58
60
|
# Records the data from a result.
|
61
|
+
#
|
59
62
|
# Minitest::Result source:
|
60
63
|
# https://github.com/seattlerb/minitest/blob/f4f57afaeb3a11bd0b86ab0757704cb78db96cf4/lib/minitest.rb#L504
|
61
64
|
def record(result)
|
65
|
+
# Convert a Minitest Result into an "issue" to more consistently expose the data needed to
|
66
|
+
# adjust the failure output to the type of failure
|
62
67
|
issue = Heat::Issue.new(result)
|
63
68
|
|
69
|
+
timer.increment_counts(issue.result.assertions)
|
64
70
|
results.record(issue)
|
65
71
|
map.add(*issue.to_hit) if issue.hit?
|
66
72
|
|
@@ -69,7 +75,7 @@ module Minitest
|
|
69
75
|
|
70
76
|
# Outputs the summary of the run.
|
71
77
|
def report
|
72
|
-
|
78
|
+
timer.stop!
|
73
79
|
|
74
80
|
# A couple of blank lines to create some breathing room
|
75
81
|
output.newline
|
@@ -80,12 +86,14 @@ module Minitest
|
|
80
86
|
# This way, as you fix issues, the list gets shorter, and eventually the least critical
|
81
87
|
# issues will be displayed without scrolling once more problematic issues are resolved.
|
82
88
|
%i[slows painfuls skips failures brokens errors].each do |issue_category|
|
89
|
+
next unless show?(issue_category)
|
90
|
+
|
83
91
|
results.send(issue_category).each { |issue| output.issue_details(issue) }
|
84
92
|
end
|
85
93
|
|
86
94
|
# Display a short summary of the total issue counts fore ach category as well as performance
|
87
95
|
# details for the test suite as a whole
|
88
|
-
output.compact_summary(results)
|
96
|
+
output.compact_summary(results, timer)
|
89
97
|
|
90
98
|
# If there were issues, shows a short heat map summary of which files and lines were the most
|
91
99
|
# common sources of issues
|
@@ -99,5 +107,23 @@ module Minitest
|
|
99
107
|
def passed?
|
100
108
|
results.errors.empty? && results.failures.empty?
|
101
109
|
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def no_problems?
|
114
|
+
!results.problems?
|
115
|
+
end
|
116
|
+
|
117
|
+
def no_problems_or_skips?
|
118
|
+
!results.problems? && !results.skips.any?
|
119
|
+
end
|
120
|
+
|
121
|
+
def show?(issue_category)
|
122
|
+
case issue_category
|
123
|
+
when :skips then no_problems?
|
124
|
+
when :painfuls, :slows then no_problems_or_skips?
|
125
|
+
else true
|
126
|
+
end
|
127
|
+
end
|
102
128
|
end
|
103
129
|
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.7
|
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-10-
|
11
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -158,6 +158,7 @@ files:
|
|
158
158
|
- lib/minitest/heat/output/token.rb
|
159
159
|
- lib/minitest/heat/results.rb
|
160
160
|
- lib/minitest/heat/source.rb
|
161
|
+
- lib/minitest/heat/timer.rb
|
161
162
|
- lib/minitest/heat/version.rb
|
162
163
|
- lib/minitest/heat_plugin.rb
|
163
164
|
- lib/minitest/heat_reporter.rb
|