minitest-utils 0.6.2 → 0.6.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 024d6a1258ae6965948fb0862e13894c53473be4baf1456654c5eb9cc63b1f18
4
- data.tar.gz: ce95d624481c9164f5d6885633067d69df8d9dc1dc603c5d07cc56cc9072d61e
3
+ metadata.gz: 17d94a9022a755b8792cfd445718e67547a7090cf16f2355320c9b89ae225e32
4
+ data.tar.gz: 7e2f7eb222ae4a000493f388a3e5a814b5fd419d44c42d01398fda4787acb088
5
5
  SHA512:
6
- metadata.gz: 8a2af19a249e434607d3297be303c773446977509a6d8534966700e9316eef054af5dd4c6d7836fee9d72b20079770dfc65cc0ac302916e9a373b0ab3778682f
7
- data.tar.gz: 61623224c5f752cf219ba8d87739d9a6878a4a42de54be01c1b5046bd183e69924693c8a9ba5fba198965e6948576f541c7dc1e161fed2eaafe1da948c678256
6
+ metadata.gz: 5d739413224b4e2fc86603ec8d95e5d8c5d83b5b8339b6f5d9be9f7af8078ae628c2f5ae667481b2b646c006bcd42385dad1ab14e7f98b8ad0b06d074a5cbb1b
7
+ data.tar.gz: 902bfb2db3d7f3ceefd3ab28646ae0d97a47d50a1f9c9748a723f6cf6c7a27410d1a2f0d76ad5b235cde23dc1125c1203fd1753763f7d728df8109ddf53d3ef3
@@ -51,5 +51,4 @@ jobs:
51
51
  env:
52
52
  BUNDLE_GEMFILE: ${{ matrix.gemfile }}
53
53
  run: |
54
- bundle exec exe/mt
55
- bundle exec rubocop
54
+ bundle exec rake
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .minitestfailures
data/README.md CHANGED
@@ -113,7 +113,14 @@ end
113
113
 
114
114
  ## Running tests
115
115
 
116
- `minitest-utils` comes with a runner: `mt`.
116
+ `minitest-utils` comes with a runner: `mt` or `minitest`.
117
+
118
+ > [!WARNING]
119
+ >
120
+ > When using this test runner, you must change your test helper and replace
121
+ > `require "minitest/autorun"` with
122
+ > `require "minitest/autorun" unless ENV["MT_RUNNER"]`. This way you can use
123
+ > both the runner and rake.
117
124
 
118
125
  You can run specific files by using `file:number`.
119
126
 
@@ -155,10 +162,9 @@ test/fixtures
155
162
 
156
163
  ## Screenshots
157
164
 
158
- ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/light-failing.png)
159
- ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/light-success.png)
160
- ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/dark-failing.png)
161
- ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/dark-success.png)
165
+ ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/detect-slow-tests.png)
166
+ ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/replay-command.png)
167
+ ![](https://raw.githubusercontent.com/fnando/minitest-utils/main/screenshots/slow-tests.png)
162
168
 
163
169
  ## Rails extensions
164
170
 
data/exe/minitest CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ ENV["MT_RUNNER"] = "true"
4
5
  require_relative "../lib/minitest/utils/cli"
5
6
  Minitest::Utils::CLI.loaded_via_bundle_exec = ENV.key?("BUNDLER_VERSION")
6
7
  Minitest::Utils::CLI.new(ARGV.dup).start
data/exe/mt CHANGED
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative "../lib/minitest/utils/cli"
5
- Minitest::Utils::CLI.loaded_via_bundle_exec = ENV.key?("BUNDLER_VERSION")
6
- Minitest::Utils::CLI.new(ARGV.dup).start
4
+ load File.join(__dir__, "minitest")
@@ -28,14 +28,6 @@ module Minitest
28
28
  OptionParser.new do |parser|
29
29
  parser.banner = ""
30
30
 
31
- parser.on_tail("-h", "--help", "Show this message") do
32
- matches = parser.to_a.map do |line|
33
- line.match(MATCHER).named_captures.transform_keys(&:to_sym)
34
- end
35
- print_help(matches)
36
- exit
37
- end
38
-
39
31
  parser.on("-n", "--name=NAME",
40
32
  "Run tests that match this name") do |v|
41
33
  options[:name] = v
@@ -58,6 +50,14 @@ module Minitest
58
50
  options[:slow_threshold] = v.to_f
59
51
  end
60
52
 
53
+ parser.on("--no-color", "Disable colored output.") do
54
+ options[:no_color] = true
55
+ end
56
+
57
+ parser.on("--watch", "Watch for changes, and re-run tests.") do
58
+ options[:watch] = true
59
+ end
60
+
61
61
  parser.on(
62
62
  "-e",
63
63
  "--exclude=PATTERN",
@@ -65,6 +65,14 @@ module Minitest
65
65
  ) do |v|
66
66
  options[:exclude] = v
67
67
  end
68
+
69
+ parser.on_tail("-h", "--help", "Show this message") do
70
+ matches = parser.to_a.map do |line|
71
+ line.match(MATCHER).named_captures.transform_keys(&:to_sym)
72
+ end
73
+ print_help(matches)
74
+ exit
75
+ end
68
76
  end.parse!(@args)
69
77
 
70
78
  run
@@ -106,11 +114,66 @@ module Minitest
106
114
  bundler = "bundle exec " if self.class.loaded_via_bundle_exec
107
115
 
108
116
  ENV["MT_TEST_COMMAND"] =
109
- "#{bundler}mt %{location}:%{line} # %{description}"
117
+ "#{bundler}mt %{location}:%{line} #{color('# %{description}', :blue)}"
110
118
 
111
119
  ARGV.clear
112
- ARGV.push(*minitest_args)
113
- Minitest.autorun
120
+ ARGV.push(*to_shell(minitest_options))
121
+
122
+ if options[:watch]
123
+ gem "listen"
124
+ require "listen"
125
+ pid = nil
126
+
127
+ listen =
128
+ Listen.to(Dir.pwd, only: /(\.rb|Gemfile\.lock)$/) do |*changed, _|
129
+ next if pid
130
+
131
+ $stdout.clear_screen
132
+
133
+ # Make a list of test files that have been changed.
134
+ changed = changed.flatten.filter_map do |file|
135
+ if file.end_with?("_test.rb")
136
+ Pathname(file).relative_path_from(Dir.pwd).to_s
137
+ end
138
+ end
139
+
140
+ options = minitest_options
141
+ .slice(:slow, :hide_slow, :no_color, :slow_threshold)
142
+
143
+ # Load the list of failures from the last run.
144
+ failures = JSON.load_file(".minitestfailures") rescue [] # rubocop:disable Style/RescueModifier
145
+ options[:name] = "/^#{failures.join('|')}$/" if failures.any?
146
+
147
+ # If there are no failures, run the changed files.
148
+ changed = [] if failures.any?
149
+
150
+ pid = Process.spawn(
151
+ $PROGRAM_NAME,
152
+ *to_shell(options),
153
+ *changed,
154
+ chdir: Dir.pwd
155
+ )
156
+ Process.wait(pid)
157
+ pid = nil
158
+ end
159
+ end
160
+
161
+ if options[:watch]
162
+ pid = Process.spawn(
163
+ $PROGRAM_NAME,
164
+ *to_shell(minitest_options),
165
+ chdir: Dir.pwd
166
+ )
167
+ Process.wait(pid)
168
+ pid = nil
169
+ listen.start
170
+ sleep
171
+ else
172
+ Minitest.autorun
173
+ end
174
+ rescue Interrupt
175
+ Process.kill("INT", pid) if pid
176
+ puts "Exiting..."
114
177
  end
115
178
 
116
179
  def minitest_args
@@ -120,6 +183,7 @@ module Minitest
120
183
  args += ["--slow", options[:slow]] if options[:slow]
121
184
  args += ["--name", "/#{only.join('|')}/"] unless only.empty?
122
185
  args += ["--hide-slow"] if options[:hide_slow]
186
+ args += ["--no-color"] if options[:no_color]
123
187
 
124
188
  if options[:slow_threshold]
125
189
  threshold = options[:slow_threshold].to_s
@@ -130,6 +194,33 @@ module Minitest
130
194
  args.map(&:to_s)
131
195
  end
132
196
 
197
+ def to_shell(args)
198
+ args
199
+ .transform_keys {|key| "--#{key.to_s.tr('_', '-')}" }
200
+ .to_a
201
+ .flatten
202
+ .reject { _1&.is_a?(TrueClass) }
203
+ .map(&:to_s)
204
+ end
205
+
206
+ def minitest_options
207
+ args = {}
208
+ args[:seed] = options[:seed]
209
+ args[:exclude] = options[:exclude] if options[:exclude]
210
+ args[:slow] = options[:slow] if options[:slow]
211
+ args[:name] = "/#{only.join('|')}/" unless only.empty?
212
+ args[:hide_slow] = options[:hide_slow] if options[:hide_slow]
213
+ args[:no_color] = options[:no_color] if options[:no_color]
214
+
215
+ if options[:slow_threshold]
216
+ threshold = options[:slow_threshold].to_s
217
+ threshold = threshold.gsub(/\.0+$/, "").delete_suffix(".")
218
+ args[:slow_threshold] = threshold
219
+ end
220
+
221
+ args
222
+ end
223
+
133
224
  def files
134
225
  @files ||= begin
135
226
  files = @args
@@ -204,9 +295,11 @@ module Minitest
204
295
  end
205
296
 
206
297
  def options
207
- @options ||= {
208
- seed: (ENV["SEED"] || srand).to_i % 0xFFFF
209
- }
298
+ @options ||= {seed: new_seed}
299
+ end
300
+
301
+ def new_seed
302
+ (ENV["SEED"] || srand).to_i % 0xFFFF
210
303
  end
211
304
 
212
305
  BANNER = <<~TEXT
@@ -229,20 +322,11 @@ module Minitest
229
322
  $ mt test/models --exclude /validations/
230
323
  TEXT
231
324
 
232
- COLOR = {
233
- red: 31,
234
- green: 32,
235
- yellow: 33,
236
- blue: 34,
237
- gray: 37
238
- }.freeze
239
-
240
325
  private def color(string, color = :default)
241
326
  return string if string.empty?
242
327
 
243
- if $stdout.tty?
244
- color = COLOR.fetch(color, 0)
245
- "\e[#{color}m#{string}\e[0m"
328
+ if $stdout.tty? && !options[:no_color] && !ARGV.include?("--no-color")
329
+ Utils.color(string, color)
246
330
  else
247
331
  string
248
332
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+
3
5
  module Minitest
4
6
  class Test
5
7
  class << self
@@ -25,17 +27,9 @@ module Minitest
25
27
  "S" => :yellow
26
28
  }.freeze
27
29
 
28
- COLOR = {
29
- red: 31,
30
- green: 32,
31
- yellow: 33,
32
- blue: 34,
33
- gray: 37
34
- }.freeze
35
-
36
30
  def initialize(*)
37
31
  super
38
- @color_enabled = io.respond_to?(:tty?) && io.tty?
32
+ @tty = io.respond_to?(:tty?) && io.tty?
39
33
  end
40
34
 
41
35
  def start
@@ -48,20 +42,31 @@ module Minitest
48
42
  print_result_code(result.result_code)
49
43
  end
50
44
 
45
+ def color(string, color = :default)
46
+ if @tty
47
+ Utils.color(string, color)
48
+ else
49
+ string
50
+ end
51
+ end
52
+
51
53
  def report
52
54
  super
53
- io.sync = true if io.respond_to?(:sync)
55
+ io.sync = true if io.respond_to?(:sync=)
54
56
 
55
- failing_results = results.reject(&:skipped?)
57
+ failing_results = results.reject(&:passed?).reject(&:skipped?)
56
58
  skipped_results = results.select(&:skipped?)
57
59
 
60
+ write_failures_json(failing_results)
61
+ print_failing_results(failing_results)
62
+ if failing_results.empty?
63
+ print_skipped_results(skipped_results, failing_results.size)
64
+ end
65
+
58
66
  color = :green
59
67
  color = :yellow if skipped_results.any?
60
68
  color = :red if failing_results.any?
61
69
 
62
- print_failing_results(failing_results)
63
- print_skipped_results(skipped_results, failing_results.size)
64
-
65
70
  io.print "\n\n"
66
71
  io.puts statistics
67
72
  io.puts color(summary, color)
@@ -75,6 +80,17 @@ module Minitest
75
80
  end
76
81
  end
77
82
 
83
+ def write_failures_json(results)
84
+ tests = results.each_with_object([]) do |result, buffer|
85
+ buffer << find_test_info(result)[:id]
86
+ end
87
+
88
+ File.write(
89
+ File.join(Dir.pwd, ".minitestfailures"),
90
+ JSON.dump(tests)
91
+ )
92
+ end
93
+
78
94
  def slow_threshold_for(test_case)
79
95
  test_case[:slow_threshold] || Minitest.options[:slow_threshold] || 0.1
80
96
  end
@@ -118,7 +134,8 @@ module Minitest
118
134
  prefix = "#{index + 1}) "
119
135
  padding = " " * prefix.size
120
136
 
121
- io.puts color("#{prefix}#{info[:description]} (#{duration})", :red)
137
+ io.puts color("#{prefix}#{info[:description]} (#{duration})",
138
+ :red)
122
139
  io.puts color("#{padding}#{location}", :blue)
123
140
  io.puts
124
141
  end
@@ -256,23 +273,11 @@ module Minitest
256
273
  end
257
274
 
258
275
  private def print_result_code(result_code)
259
- result_code = color(result_code, COLOR_FOR_RESULT_CODE[result_code])
276
+ result_code = color(result_code,
277
+ COLOR_FOR_RESULT_CODE[result_code])
260
278
  io.print result_code
261
279
  end
262
280
 
263
- private def color(string, color = :default)
264
- if color_enabled?
265
- color = COLOR.fetch(color, 0)
266
- "\e[#{color}m#{string}\e[0m"
267
- else
268
- string
269
- end
270
- end
271
-
272
- private def color_enabled?
273
- @color_enabled
274
- end
275
-
276
281
  private def pluralize(word, count)
277
282
  case count
278
283
  when 0
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Minitest
4
4
  module Utils
5
- VERSION = "0.6.2"
5
+ VERSION = "0.6.3"
6
6
  end
7
7
  end
@@ -1,6 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Minitest
4
+ class << self
5
+ attr_accessor :options
6
+ end
7
+
8
+ self.options = {}
9
+
4
10
  module Utils
5
11
  require "minitest"
6
12
  require "pathname"
@@ -9,6 +15,27 @@ module Minitest
9
15
  require_relative "utils/extension"
10
16
  require_relative "utils/test_notifier_reporter"
11
17
 
18
+ COLOR = {
19
+ red: 31,
20
+ green: 32,
21
+ yellow: 33,
22
+ blue: 34,
23
+ gray: 37
24
+ }.freeze
25
+
26
+ def self.color(string, color = :default)
27
+ if color_enabled?
28
+ color = COLOR.fetch(color, 0)
29
+ "\e[#{color}m#{string}\e[0m"
30
+ else
31
+ string
32
+ end
33
+ end
34
+
35
+ def self.color_enabled?
36
+ !ENV["NO_COLOR"] && !Minitest.options[:no_color]
37
+ end
38
+
12
39
  load_lib = lambda do |path, &block|
13
40
  require path
14
41
  block&.call
@@ -4,12 +4,6 @@ require_relative "utils/reporter"
4
4
  require_relative "utils/test_notifier_reporter"
5
5
 
6
6
  module Minitest
7
- class << self
8
- attr_accessor :options
9
- end
10
-
11
- self.options = {}
12
-
13
7
  def self.plugin_utils_options(opts, options)
14
8
  Minitest.options = options
15
9
 
@@ -17,6 +11,10 @@ module Minitest
17
11
  options[:slow] = true
18
12
  end
19
13
 
14
+ opts.on("--no-color", "Disable colored output") do
15
+ options[:no_color] = true
16
+ end
17
+
20
18
  opts.on("--hide-slow", "Hide list of slow tests") do
21
19
  options[:hide_slow] = true
22
20
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
+ spec.add_dependency "listen"
22
23
  spec.add_dependency "minitest"
23
24
  spec.add_development_dependency "bundler"
24
25
  spec.add_development_dependency "rake"
Binary file
Binary file
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-15 00:00:00.000000000 Z
10
+ date: 2025-03-16 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: listen
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
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'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: minitest
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -147,10 +161,10 @@ files:
147
161
  - lib/minitest/utils/version.rb
148
162
  - lib/minitest/utils_plugin.rb
149
163
  - minitest-utils.gemspec
150
- - screenshots/dark-failing.png
151
- - screenshots/dark-success.png
152
- - screenshots/light-failing.png
153
- - screenshots/light-success.png
164
+ - screenshots/detect-slow-tests.png
165
+ - screenshots/replay-command.png
166
+ - screenshots/screenshots.pxd
167
+ - screenshots/slow-tests.png
154
168
  homepage: http://github.com/fnando/minitest-utils
155
169
  licenses: []
156
170
  metadata:
Binary file
Binary file
Binary file
Binary file