minitest-heat 0.0.6 → 0.0.7
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/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
|