minitest-heat 2.1.0 → 2.2.0

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.
@@ -10,9 +10,7 @@ module Minitest
10
10
  attr_accessor :results, :timer
11
11
 
12
12
  # Explicitly define issues to avoid Forwardable warning about Object#issues private method
13
- def issues
14
- @results.issues
15
- end
13
+ def issues = @results.issues
16
14
 
17
15
  def_delegators :@results, :errors, :brokens, :failures, :skips, :painfuls, :slows, :problems?
18
16
 
@@ -68,17 +66,11 @@ module Minitest
68
66
  counts_with_separators
69
67
  end
70
68
 
71
- def error_count_token
72
- issue_count_token(:error, errors)
73
- end
69
+ def error_count_token = issue_count_token(:error, errors)
74
70
 
75
- def broken_count_token
76
- issue_count_token(:broken, brokens)
77
- end
71
+ def broken_count_token = issue_count_token(:broken, brokens)
78
72
 
79
- def failure_count_token
80
- issue_count_token(:failure, failures)
81
- end
73
+ def failure_count_token = issue_count_token(:failure, failures)
82
74
 
83
75
  def skip_count_token
84
76
  style = problems? ? :muted : :skipped
@@ -86,34 +78,24 @@ module Minitest
86
78
  end
87
79
 
88
80
  def painful_count_token
89
- style = problems? || skips.any? ? :muted : :painful
90
- issue_count_token(style, painfuls, name: 'Painfully Slow')
81
+ issue_count_token(secondary_style(:painful), painfuls, name: 'Painfully Slow')
91
82
  end
92
83
 
93
84
  def slow_count_token
94
- style = problems? || skips.any? ? :muted : :slow
95
- issue_count_token(style, slows, name: 'Slow')
85
+ issue_count_token(secondary_style(:slow), slows, name: 'Slow')
96
86
  end
97
87
 
98
- def test_count_token
99
- [:default, pluralize(timer.test_count, 'test').to_s]
100
- end
88
+ def secondary_style(style) = problems? || skips.any? ? :muted : style
101
89
 
102
- def tests_performance_token
103
- [:default, " (#{timer.tests_per_second}/s)"]
104
- end
90
+ def test_count_token = [:default, pluralize(timer.test_count, 'test').to_s]
105
91
 
106
- def assertions_count_token
107
- [:default, pluralize(timer.assertion_count, 'assertion').to_s]
108
- end
92
+ def tests_performance_token = [:default, " (#{timer.tests_per_second}/s)"]
109
93
 
110
- def assertions_performance_token
111
- [:default, " (#{timer.assertions_per_second}/s)"]
112
- end
94
+ def assertions_count_token = [:default, pluralize(timer.assertion_count, 'assertion').to_s]
113
95
 
114
- def timing_token
115
- [:bold, "#{timer.total_time.round(2)}s"]
116
- end
96
+ def assertions_performance_token = [:default, " (#{timer.assertions_per_second}/s)"]
97
+
98
+ def timing_token = [:bold, "#{timer.total_time.round(2)}s"]
117
99
 
118
100
  def issue_count_token(type, collection, name: type.capitalize)
119
101
  return nil if collection.empty?
@@ -121,13 +103,9 @@ module Minitest
121
103
  [type, pluralize(collection.size, name)]
122
104
  end
123
105
 
124
- def spacer_token
125
- Output::TOKENS[:spacer]
126
- end
106
+ def spacer_token = Output::TOKENS[:spacer]
127
107
 
128
- def join_token
129
- [:default, ' with ']
130
- end
108
+ def join_token = [:default, ' with ']
131
109
  end
132
110
  end
133
111
  end
@@ -63,9 +63,7 @@ module Minitest
63
63
  # three lines. Or it could be something end users could disable in order to reduce noise.
64
64
  #
65
65
  # @return [Boolean] true if the target line should be highlighted
66
- def highlight_key_line?
67
- HIGHLIGHT_KEY_LINE
68
- end
66
+ def highlight_key_line? = HIGHLIGHT_KEY_LINE
69
67
 
70
68
  # The number of spaces each line of code should be indented. Currently defaults to 2 in
71
69
  # order to provide visual separation between test failures, but in the future, it could
@@ -75,9 +73,7 @@ module Minitest
75
73
  # option that would reduce the space used.
76
74
  #
77
75
  # @return [type] [description]
78
- def indentation
79
- DEFAULT_INDENTATION_SPACES
80
- end
76
+ def indentation = DEFAULT_INDENTATION_SPACES
81
77
 
82
78
  private
83
79
 
@@ -113,18 +109,14 @@ module Minitest
113
109
  # @param line_number [Integer,String] the digits representing the line number
114
110
  #
115
111
  # @return [Array] the style/content token for the current line number
116
- def line_number_token(style, line_number)
117
- [style, "#{' ' * indentation}#{line_number.to_s.rjust(max_line_number_digits)} "]
118
- end
112
+ def line_number_token(style, line_number) = [style, "#{' ' * indentation}#{line_number.to_s.rjust(max_line_number_digits)} "]
119
113
 
120
114
  # The token representing the content of a given line of code.
121
115
  # @param style [Symbol] the symbol representing the style for the line of code token
122
116
  # @param line_number [Integer,String] the content of the line of code
123
117
  #
124
118
  # @return [Array] the style/content token for the current line of code
125
- def line_of_code_token(style, line_of_code)
126
- [style, line_of_code]
127
- end
119
+ def line_of_code_token(style, line_of_code) = [style, line_of_code]
128
120
  end
129
121
  end
130
122
  end
@@ -6,6 +6,7 @@ module Minitest
6
6
  # Provides a convenient interface for creating console-friendly output while ensuring
7
7
  # consistency in the applied styles.
8
8
  class Token
9
+ # Raised when an unrecognized style key is used
9
10
  class InvalidStyle < ArgumentError; end
10
11
 
11
12
  STYLES = {
@@ -23,6 +24,28 @@ module Minitest
23
24
  muted: %i[light default]
24
25
  }.freeze
25
26
 
27
+ ESC_SEQUENCE = "\e["
28
+ END_SEQUENCE = 'm'
29
+
30
+ WEIGHTS = {
31
+ default: 0,
32
+ bold: 1,
33
+ light: 2,
34
+ italic: 3
35
+ }.freeze
36
+
37
+ COLORS = {
38
+ black: 30,
39
+ red: 31,
40
+ green: 32,
41
+ yellow: 33,
42
+ blue: 34,
43
+ magenta: 35,
44
+ cyan: 36,
45
+ gray: 37,
46
+ default: 39
47
+ }.freeze
48
+
26
49
  attr_accessor :style_key, :content
27
50
 
28
51
  def initialize(style_key, content)
@@ -47,28 +70,6 @@ module Minitest
47
70
 
48
71
  private
49
72
 
50
- ESC_SEQUENCE = "\e["
51
- END_SEQUENCE = 'm'
52
-
53
- WEIGHTS = {
54
- default: 0,
55
- bold: 1,
56
- light: 2,
57
- italic: 3
58
- }.freeze
59
-
60
- COLORS = {
61
- black: 30,
62
- red: 31,
63
- green: 32,
64
- yellow: 33,
65
- blue: 34,
66
- magenta: 35,
67
- cyan: 36,
68
- gray: 37,
69
- default: 39
70
- }.freeze
71
-
72
73
  def style_string
73
74
  "#{ESC_SEQUENCE}#{weight};#{color}#{END_SEQUENCE}"
74
75
  end
@@ -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 # rubocop:disable Metrics/ClassLength
14
+ class Output
15
15
  SYMBOLS = {
16
16
  middot: '·',
17
17
  arrow: '➜',
@@ -33,12 +33,12 @@ module Minitest
33
33
  end
34
34
  end
35
35
 
36
- def print(*args)
37
- stream.print(*args)
36
+ def print(*)
37
+ stream.print(*)
38
38
  end
39
39
 
40
- def puts(*args)
41
- stream.puts(*args)
40
+ def puts(*)
41
+ stream.puts(*)
42
42
  end
43
43
  alias newline puts
44
44
 
@@ -152,12 +152,10 @@ module Minitest
152
152
  def print_tokens(lines_of_tokens)
153
153
  lines_of_tokens.each do |tokens|
154
154
  tokens.each do |token|
155
- begin
156
- print Token.new(*token).to_s(token_format)
157
- rescue ArgumentError => e
158
- # Token format error - output debug info and continue
159
- puts "Token error (#{e.message}): #{token.inspect}"
160
- end
155
+ print Token.new(*token).to_s(token_format)
156
+ rescue ArgumentError => e
157
+ # Token format error - output debug info and continue
158
+ puts "Token error (#{e.message}): #{token.inspect}"
161
159
  end
162
160
  newline
163
161
  end
@@ -15,21 +15,18 @@ module Minitest
15
15
  @line_number = Integer(line_number)
16
16
  @max_line_count = max_line_count
17
17
  @context = context
18
+ @raw_lines = nil
18
19
  end
19
20
 
20
21
  # Returns relevant lines as a hash with line numbers as the keys
21
22
  #
22
23
  # @return [Hash] hash of relevant lines with line numbers as keys
23
- def to_h
24
- line_numbers.map(&:to_s).zip(lines).to_h
25
- end
24
+ def to_h = line_numbers.map(&:to_s).zip(lines).to_h
26
25
 
27
26
  # Looks up the line of code referenced
28
27
  #
29
28
  # @return [String] the line of code at filename:line_number
30
- def line
31
- file_lines[line_number - 1]
32
- end
29
+ def line = file_lines[line_number - 1]
33
30
 
34
31
  # Looks up the available lines of code around the referenced line number
35
32
  #
@@ -43,9 +40,7 @@ module Minitest
43
40
  # Line numbers for the returned lines
44
41
  #
45
42
  # @return [Array<Integer>] the line numbers corresponding to the lines returned
46
- def line_numbers
47
- (first_line_number..last_line_number).to_a.uniq
48
- end
43
+ def line_numbers = (first_line_number..last_line_number).to_a.uniq
49
44
 
50
45
  # Reads (and chomps) the lines of the target file
51
46
  #
@@ -68,9 +63,7 @@ module Minitest
68
63
  # The largest possible value for line numbers
69
64
  #
70
65
  # @return [Integer] the last line number of the file
71
- def max_line_number
72
- file_lines.length
73
- end
66
+ def max_line_number = file_lines.length
74
67
 
75
68
  # The number of the first line of code to return
76
69
  #
@@ -79,7 +72,7 @@ module Minitest
79
72
  target = line_number - first_line_offset - leftover_trailing_lines_count
80
73
 
81
74
  # Can't go earlier than the first line
82
- target < 1 ? 1 : target
75
+ [target, 1].max
83
76
  end
84
77
 
85
78
  # The number of the last line of code to return
@@ -89,7 +82,7 @@ module Minitest
89
82
  target = line_number + last_line_offset + leftover_preceding_lines_count
90
83
 
91
84
  # Can't go past the end of the file
92
- target > max_line_number ? max_line_number : target
85
+ [target, max_line_number].min
93
86
  end
94
87
 
95
88
  # The target number of preceding lines to include
@@ -135,21 +128,15 @@ module Minitest
135
128
  end
136
129
 
137
130
  # The total number of lines to include in addition to the primary line
138
- def other_lines_count
139
- max_line_count - 1
140
- end
131
+ def other_lines_count = max_line_count - 1
141
132
 
142
- def preceding_lines_split_count
143
- # Round up preceding lines if it's uneven because preceding lines are more likely to be
144
- # helpful when debugging
145
- (other_lines_count / 2).round(0, half: :up)
146
- end
133
+ # Round up preceding lines if it's uneven because preceding lines are more likely to be
134
+ # helpful when debugging
135
+ def preceding_lines_split_count = (other_lines_count / 2).round(0, half: :up)
147
136
 
148
- def trailing_lines_split_count
149
- # Round down preceding lines because they provide context in the file but don't contribute
150
- # in terms of the code that led to the error
151
- (other_lines_count / 2).round(0, half: :down)
152
- end
137
+ # Round down preceding lines because they provide context in the file but don't contribute
138
+ # in terms of the code that led to the error
139
+ def trailing_lines_split_count = (other_lines_count / 2).round(0, half: :down)
153
140
  end
154
141
  end
155
142
  end
@@ -36,12 +36,10 @@ module Minitest
36
36
  # returns a zero that would be problematic as a denomitor in calculating average times
37
37
  #
38
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
39
+ # Don't return 0. The time can end up being 0 for a new or realy fast test suite, and
40
+ # dividing by 0 doesn't go well when determining average time, so this ensures it uses a
41
+ # close-enough-but-not-zero value.
42
+ def total_time = delta.zero? ? 0.01 : delta
45
43
 
46
44
  # Records the test and assertion counts for a given test outcome
47
45
  # @param count [Integer] the number of assertions from the test
@@ -55,16 +53,12 @@ module Minitest
55
53
  # Provides a nice rounded answer for about how many tests were completed per second
56
54
  #
57
55
  # @return [Float] the average number of tests completed per second
58
- def tests_per_second
59
- (test_count / total_time).round(2)
60
- end
56
+ def tests_per_second = (test_count / total_time).round(2)
61
57
 
62
58
  # Provides a nice rounded answer for about how many assertions were completed per second
63
59
  #
64
60
  # @return [Float] the average number of assertions completed per second
65
- def assertions_per_second
66
- (assertion_count / total_time).round(2)
67
- end
61
+ def assertions_per_second = (assertion_count / total_time).round(2)
68
62
 
69
63
  # Generates a hash representation for JSON serialization
70
64
  #
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Minitest
4
4
  module Heat
5
- VERSION = '2.1.0'
5
+ VERSION = '2.2.0'
6
6
  end
7
7
  end
@@ -2,7 +2,8 @@
2
2
 
3
3
  require_relative 'heat_reporter'
4
4
 
5
- module Minitest # rubocop:disable Style/Documentation
5
+ # :reek:IrresponsibleModule - reopening Minitest module for plugin registration
6
+ module Minitest
6
7
  def self.plugin_heat_options(opts, options)
7
8
  opts.on '--heat-json', 'Output results as JSON instead of human-readable format' do
8
9
  options[:heat_json] = true
@@ -10,6 +11,8 @@ module Minitest # rubocop:disable Style/Documentation
10
11
  end
11
12
 
12
13
  def self.plugin_heat_init(options)
14
+ return if reporter.reporters.any? { |existing| existing.is_a?(HeatReporter) }
15
+
13
16
  io = options.fetch(:io, $stdout)
14
17
 
15
18
  reporter.reporters.reject! do |reporter|
@@ -38,6 +38,7 @@ module Minitest
38
38
  super()
39
39
 
40
40
  @options = options
41
+ @recording_error = false
41
42
 
42
43
  @timer = Heat::Timer.new
43
44
  @results = Heat::Results.new
@@ -56,8 +57,8 @@ module Minitest
56
57
  end
57
58
 
58
59
  # About to start running a test. This allows a reporter to show that it is starting or that we
59
- # are in the middle of a test run.
60
- def prerecord(klass, name); end
60
+ # are in the middle of a test run. Parameters required by Minitest::AbstractReporter interface.
61
+ def prerecord(_klass, _name); end
61
62
 
62
63
  # Records the data from a result.
63
64
  #
@@ -77,23 +78,25 @@ module Minitest
77
78
  # Show the marker (skip for JSON output)
78
79
  output.marker(issue.type) unless json_output?
79
80
  rescue StandardError => e
81
+ @recording_error = true
80
82
  display_exception_guidance(e)
81
83
  end
82
84
 
83
85
  def display_exception_guidance(exception)
84
- output.newline
85
- puts 'Sorry, but Minitest Heat encountered an exception recording an issue. Disabling Minitest Heat will get you back on track.'
86
- puts 'Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues'
87
- puts "#{exception.message}:"
86
+ warn ''
87
+ warn 'Sorry, but Minitest Heat encountered an exception recording an issue. Disabling Minitest Heat will get you back on track.'
88
+ warn 'Please use the following exception details to submit an issue at https://github.com/garrettdimon/minitest-heat/issues'
89
+ warn "#{exception.message}:"
88
90
  exception.backtrace.each do |line|
89
- puts " #{line}"
91
+ warn " #{line}"
90
92
  end
91
- output.newline
93
+ warn ''
92
94
  end
93
95
 
94
96
  # Outputs the summary of the run.
95
97
  def report
96
98
  timer.stop!
99
+ warn "Nothing ran for filter: #{test_filter}" if empty_filtered_run?
97
100
 
98
101
  if json_output?
99
102
  output_json
@@ -105,26 +108,27 @@ module Minitest
105
108
  # Whether to output JSON instead of human-readable text
106
109
  #
107
110
  # @return [Boolean] true if --heat-json flag was passed
108
- def json_output?
109
- options[:heat_json]
110
- end
111
+ def json_output? = options[:heat_json]
111
112
 
112
113
  # Did this run pass?
113
- def passed?
114
- results.errors.empty? && results.failures.empty?
115
- end
114
+ def passed? = !@recording_error && !results.problems? && !empty_filtered_run?
116
115
 
117
116
  private
118
117
 
118
+ def test_filter = options[:include] || options[:filter]
119
+
120
+ def empty_filtered_run? = test_filter && timer.test_count.zero?
121
+
119
122
  def output_json
120
123
  require 'json'
124
+ require 'time'
121
125
  output.stream.puts JSON.pretty_generate(json_results)
122
126
  end
123
127
 
124
128
  def json_results
125
129
  {
126
130
  version: '1.0',
127
- status: results.problems? ? 'failed' : 'passed',
131
+ status: passed? ? 'passed' : 'failed',
128
132
  timestamp: Time.now.iso8601,
129
133
  statistics: results.statistics,
130
134
  timing: timer.to_h,
@@ -31,13 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ['lib']
33
33
 
34
- spec.add_runtime_dependency 'minitest'
35
-
36
- spec.add_development_dependency 'awesome_print'
37
- spec.add_development_dependency 'debug'
38
- spec.add_development_dependency 'rubocop'
39
- spec.add_development_dependency 'rubocop-minitest'
40
- spec.add_development_dependency 'rubocop-rake'
41
- spec.add_development_dependency 'simplecov'
42
- spec.add_development_dependency 'simplecov_json_formatter'
34
+ spec.add_dependency 'minitest', '>= 5.22.3', '< 7'
43
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest-heat
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett Dimon
@@ -15,112 +15,20 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
- - !ruby/object:Gem::Dependency
27
- name: awesome_print
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :development
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
40
- - !ruby/object:Gem::Dependency
41
- name: debug
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0'
47
- type: :development
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- - !ruby/object:Gem::Dependency
55
- name: rubocop
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
- type: :development
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
18
+ version: 5.22.3
19
+ - - "<"
66
20
  - !ruby/object:Gem::Version
67
- version: '0'
68
- - !ruby/object:Gem::Dependency
69
- name: rubocop-minitest
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- type: :development
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
82
- - !ruby/object:Gem::Dependency
83
- name: rubocop-rake
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: '0'
89
- type: :development
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: simplecov
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: '0'
103
- type: :development
21
+ version: '7'
22
+ type: :runtime
104
23
  prerelease: false
105
24
  version_requirements: !ruby/object:Gem::Requirement
106
25
  requirements:
107
26
  - - ">="
108
27
  - !ruby/object:Gem::Version
109
- version: '0'
110
- - !ruby/object:Gem::Dependency
111
- name: simplecov_json_formatter
112
- requirement: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- type: :development
118
- prerelease: false
119
- version_requirements: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - ">="
28
+ version: 5.22.3
29
+ - - "<"
122
30
  - !ruby/object:Gem::Version
123
- version: '0'
31
+ version: '7'
124
32
  description: Presents test results in a visual manner to guide you to where to look
125
33
  first.
126
34
  email:
@@ -129,10 +37,14 @@ executables: []
129
37
  extensions: []
130
38
  extra_rdoc_files: []
131
39
  files:
40
+ - ".flayignore"
132
41
  - ".github/FUNDING.yml"
133
42
  - ".github/workflows/main.yml"
134
43
  - ".github/workflows/release.yml"
135
44
  - ".gitignore"
45
+ - ".reek.yml"
46
+ - ".reviewer.yml"
47
+ - ".reviewer_history.yml"
136
48
  - ".rubocop.yml"
137
49
  - CHANGELOG.md
138
50
  - CODE_OF_CONDUCT.md
@@ -144,6 +56,7 @@ files:
144
56
  - Rakefile
145
57
  - bin/console
146
58
  - bin/setup
59
+ - favicon.svg
147
60
  - lib/minitest/heat.rb
148
61
  - lib/minitest/heat/backtrace.rb
149
62
  - lib/minitest/heat/backtrace/line_count.rb