Skip to content

Commit d4c40b6

Browse files
authored
Merge pull request rails#50941 from andrewn617/actionable-cli
Retry `ActionableError`s when running tests
2 parents 3d418c0 + bc9c665 commit d4c40b6

File tree

5 files changed

+93
-7
lines changed

5 files changed

+93
-7
lines changed

railties/CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
* Allow Actionable Errors encountered when running tests to be retried.
2+
3+
```txt
4+
Migrations are pending. To resolve this issue, run:
5+
6+
bin/rails db:migrate
7+
8+
You have 1 pending migration:
9+
10+
db/migrate/20240201213806_add_a_to_b.rb
11+
Run pending migrations? [Yn] Y
12+
== 20240201213806 AddAToB: migrating =========================================
13+
== 20240201213806 AddAToB: migrated (0.0000s) ================================
14+
15+
Running 7 tests in a single process (parallelization threshold is 50)
16+
Run options: --seed 22200
17+
18+
# Running:
19+
20+
.......
21+
22+
Finished in 0.243394s, 28.7600 runs/s, 45.1942 assertions/s.
23+
7 runs, 11 assertions, 0 failures, 0 errors, 0 skips
24+
```
25+
26+
This feature will only be present on interactive terminals.
27+
28+
*Andrew Novoselac & Gannon McGibbon*
29+
130
* Skip generating a `test` job in ci.yml when a new application is generated with the
231
`--skip-test` option.
332

railties/lib/rails/command/base.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,26 @@ def invoke_command(command, *) # :nodoc:
179179
ensure
180180
@current_subcommand = original_subcommand
181181
end
182+
183+
protected
184+
def with_actionable_errors_retried(&block)
185+
block.call
186+
rescue ActiveSupport::ActionableError => e
187+
puts e.to_s.strip
188+
exit 1 unless tty?
189+
190+
ActiveSupport::ActionableError.actions(e).each_key do |action_name|
191+
if yes? "#{action_name}? [Yn]"
192+
ActiveSupport::ActionableError.dispatch(e, action_name)
193+
return with_actionable_errors_retried(&block)
194+
end
195+
end
196+
exit 1
197+
end
198+
199+
def tty?
200+
STDOUT.tty?
201+
end
182202
end
183203
end
184204
end

railties/lib/rails/commands/test/test_command.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ def perform(*args)
3030

3131
Rails::TestUnit::Runner.parse_options(args)
3232
run_prepare_task if self.args.none?(EXACT_TEST_ARGUMENT_PATTERN)
33-
Rails::TestUnit::Runner.run(args)
33+
with_actionable_errors_retried do
34+
Rails::TestUnit::Runner.run(args)
35+
end
3436
rescue Rails::TestUnit::InvalidTestError => error
3537
say error.message
3638
end

railties/lib/rails/testing/maintain_test_schema.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
# frozen_string_literal: true
22

33
if defined?(ActiveRecord::Base)
4-
begin
5-
ActiveRecord::Migration.maintain_test_schema!
6-
rescue ActiveRecord::PendingMigrationError => e
7-
puts e.to_s.strip
8-
exit 1
9-
end
4+
5+
ActiveRecord::Migration.maintain_test_schema!
106

117
if Rails.configuration.eager_load
128
ActiveRecord::Base.descendants.each do |model|

railties/test/application/test_test.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,45 @@ def self.load_schema!
345345
assert_unsuccessful_run "models/user_test.rb", "SCHEMA LOADED!"
346346
end
347347

348+
def test_actionable_command_line_error_with_tty
349+
rails "generate", "scaffold", "user", "name:string"
350+
app_file "config/initializers/thor_yes.rb", <<-RUBY
351+
Rails::Command::Base.class_eval <<-INITIALIZER
352+
def yes?(statement, color = nil)
353+
raise ArgumentError unless statement == "Run pending migrations? [Yn]"
354+
true
355+
end
356+
357+
def tty?
358+
true
359+
end
360+
INITIALIZER
361+
RUBY
362+
363+
run_test_file("models/user_test.rb").tap do |output|
364+
assert_match "Migrations are pending. To resolve this issue, run:", output
365+
assert_match "CreateUsers: migrating", output
366+
assert_match "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips", output
367+
end
368+
end
369+
370+
def test_actionable_command_line_without_tty
371+
rails "generate", "scaffold", "user", "name:string"
372+
app_file "config/initializers/thor_yes.rb", <<-RUBY
373+
Rails::Command::Base.class_eval <<-INITIALIZER
374+
def tty?
375+
false
376+
end
377+
INITIALIZER
378+
RUBY
379+
380+
run_test_file("models/user_test.rb").tap do |output|
381+
assert_match "Migrations are pending. To resolve this issue, run:", output
382+
assert_no_match "CreateUsers: migrating", output
383+
assert_no_match "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips", output
384+
end
385+
end
386+
348387
private
349388
def assert_unsuccessful_run(name, message)
350389
result = run_test_file(name)

0 commit comments

Comments
 (0)