From 802ce8a2392d3f749e665d4f9e54790cf613aaf9 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Mon, 4 Sep 2017 02:25:26 +0930 Subject: Run in-app rails commands via fork+load where possible While this avoids shell argument parsing, we still pass through everything in our stack. --- railties/test/application/asset_debugging_test.rb | 3 +- railties/test/application/bin_setup_test.rb | 2 +- railties/test/application/generators_test.rb | 8 +- railties/test/application/help_test.rb | 4 +- .../application/initializers/frameworks_test.rb | 12 +- .../test/application/integration_test_case_test.rb | 8 +- railties/test/application/rake/dbs_test.rb | 82 ++++++------ railties/test/application/rake/dev_test.rb | 10 +- railties/test/application/rake/log_test.rb | 2 +- railties/test/application/rake/migrations_test.rb | 146 ++++++++++----------- railties/test/application/rake/restart_test.rb | 6 +- railties/test/application/rake/tmp_test.rb | 6 +- railties/test/application/rake_test.rb | 126 ++++++++---------- railties/test/application/runner_test.rb | 31 ++--- railties/test/application/test_runner_test.rb | 54 ++++---- railties/test/application/test_test.rb | 16 +-- railties/test/application/version_test.rb | 4 +- railties/test/commands/secrets_test.rb | 11 +- railties/test/isolation/abstract_unit.rb | 84 +++++++++++- railties/test/secrets_test.rb | 6 +- 20 files changed, 333 insertions(+), 288 deletions(-) (limited to 'railties/test') diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index 128040262f..cb66a66175 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -44,8 +44,7 @@ module ApplicationTests test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do # config.assets.debug and config.assets.compile are false for production environment ENV["RAILS_ENV"] = "production" - output = Dir.chdir(app_path) { `bin/rails assets:precompile --trace 2>&1` } - assert $?.success?, output + rails "assets:precompile", "--trace" # Load app env app "production" diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index a09c371033..54934dbe24 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -22,7 +22,7 @@ module ApplicationTests end RUBY - list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip } + list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip } File.write("log/test.log", "zomg!") assert_equal "[]", list_tables.call diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 9248aec2ef..47c815d221 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -31,7 +31,7 @@ module ApplicationTests end test "allow running plugin new generator inside Rails app directory" do - FileUtils.cd(rails_root) { `ruby bin/rails plugin new vendor/plugins/bukkits` } + rails "plugin", "new", "vendor/plugins/bukkits" assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb")) end @@ -167,7 +167,7 @@ module ApplicationTests config.api_only = true RUBY - FileUtils.cd(rails_root) { `bin/rails generate mailer notifier foo` } + rails "generate", "mailer", "notifier", "foo" assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.text.erb")) assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.html.erb")) end @@ -190,10 +190,10 @@ module ApplicationTests test "help does not show hidden namespaces" do FileUtils.cd(rails_root) do - output = `bin/rails generate --help` + output = rails("generate", "--help") assert_no_match "active_record:migration", output - output = `bin/rails destroy --help` + output = rails("destroy", "--help") assert_no_match "active_record:migration", output end end diff --git a/railties/test/application/help_test.rb b/railties/test/application/help_test.rb index 3a9384b927..f728fc3b85 100644 --- a/railties/test/application/help_test.rb +++ b/railties/test/application/help_test.rb @@ -14,12 +14,12 @@ class HelpTest < ActiveSupport::TestCase end test "command works" do - output = Dir.chdir(app_path) { `bin/rails help` } + output = rails("help") assert_match "The most common rails commands are", output end test "short-cut alias works" do - output = Dir.chdir(app_path) { `bin/rails -h` } + output = rails("-h") assert_match "The most common rails commands are", output end end diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index 0d02bc8a0c..d2b77bd015 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -215,20 +215,16 @@ module ApplicationTests end test "use schema cache dump" do - Dir.chdir(app_path) do - `rails generate model post title:string; - bin/rails db:migrate db:schema:cache:dump` - end + rails %w(generate model post title:string) + rails %w(db:migrate db:schema:cache:dump) require "#{app_path}/config/environment" ActiveRecord::Base.connection.drop_table("posts") # force drop posts table for test. assert ActiveRecord::Base.connection.schema_cache.data_sources("posts") end test "expire schema cache dump" do - Dir.chdir(app_path) do - `rails generate model post title:string; - bin/rails db:migrate db:schema:cache:dump db:rollback` - end + rails %w(generate model post title:string) + rails %w(db:migrate db:schema:cache:dump db:rollback) require "#{app_path}/config/environment" assert !ActiveRecord::Base.connection.schema_cache.data_sources("posts") end diff --git a/railties/test/application/integration_test_case_test.rb b/railties/test/application/integration_test_case_test.rb index 88b54af8c8..9edc907fce 100644 --- a/railties/test/application/integration_test_case_test.rb +++ b/railties/test/application/integration_test_case_test.rb @@ -15,7 +15,7 @@ module ApplicationTests end test "resets Action Mailer test deliveries" do - script("generate mailer BaseMailer welcome") + rails "generate", "mailer", "BaseMailer", "welcome" app_file "test/integration/mailer_integration_test.rb", <<-RUBY require 'test_helper' @@ -39,8 +39,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails test 2>&1` } - assert_equal 0, $?.to_i, output + output = rails("test") assert_match(/0 failures, 0 errors/, output) end end @@ -67,8 +66,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails test 2>&1` } - assert_equal 0, $?.to_i, output + output = rails("test") assert_match(/0 failures, 0 errors/, output) end end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index db88eb0fd3..391676aa31 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -28,11 +28,11 @@ module ApplicationTests def db_create_and_drop(expected_database) Dir.chdir(app_path) do - output = `bin/rails db:create` + output = rails("db:create") assert_match(/Created database/, output) assert File.exist?(expected_database) assert_equal expected_database, ActiveRecord::Base.connection_config[:database] - output = `bin/rails db:drop` + output = rails("db:drop") assert_match(/Dropped database/, output) assert !File.exist?(expected_database) end @@ -52,17 +52,16 @@ module ApplicationTests def with_database_existing Dir.chdir(app_path) do set_database_url - `bin/rails db:create` + rails "db:create" yield - `bin/rails db:drop` + rails "db:drop" end end test "db:create failure because database exists" do with_database_existing do - output = `bin/rails db:create 2>&1` + output = rails("db:create") assert_match(/already exists/, output) - assert_equal 0, $?.exitstatus end end @@ -77,7 +76,7 @@ module ApplicationTests test "db:create failure because bad permissions" do with_bad_permissions do - output = `bin/rails db:create 2>&1` + output = rails("db:create", allow_failure: true) assert_match(/Couldn't create database/, output) assert_equal 1, $?.exitstatus end @@ -85,16 +84,15 @@ module ApplicationTests test "db:drop failure because database does not exist" do Dir.chdir(app_path) do - output = `bin/rails db:drop:_unsafe --trace 2>&1` + output = rails("db:drop:_unsafe", "--trace") assert_match(/does not exist/, output) - assert_equal 0, $?.exitstatus end end test "db:drop failure because bad permissions" do with_database_existing do with_bad_permissions do - output = `bin/rails db:drop 2>&1` + output = rails("db:drop", allow_failure: true) assert_match(/Couldn't drop/, output) assert_equal 1, $?.exitstatus end @@ -103,9 +101,9 @@ module ApplicationTests def db_migrate_and_status(expected_database) Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate` - output = `bin/rails db:migrate:status` + rails "generate", "model", "book", "title:string" + rails "db:migrate" + output = rails("db:migrate:status") assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output) assert_match(/up\s+\d{14}\s+Create books/, output) end @@ -124,8 +122,8 @@ module ApplicationTests def db_schema_dump Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate db:schema:dump` + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:schema:dump" schema_dump = File.read("db/schema.rb") assert_match(/create_table \"books\"/, schema_dump) end @@ -142,8 +140,8 @@ module ApplicationTests def db_fixtures_load(expected_database) Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate db:fixtures:load` + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:fixtures:load" assert_match expected_database, ActiveRecord::Base.connection_config[:database] require "#{app_path}/app/models/book" assert_equal 2, Book.count @@ -164,8 +162,8 @@ module ApplicationTests test "db:fixtures:load with namespaced fixture" do require "#{app_path}/config/environment" Dir.chdir(app_path) do - `bin/rails generate model admin::book title:string; - bin/rails db:migrate db:fixtures:load` + rails "generate", "model", "admin::book", "title:string" + rails "db:migrate", "db:fixtures:load" require "#{app_path}/app/models/admin/book" assert_equal 2, Admin::Book.count end @@ -173,11 +171,11 @@ module ApplicationTests def db_structure_dump_and_load(expected_database) Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate db:structure:dump` + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:structure:dump" structure_dump = File.read("db/structure.sql") assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, structure_dump) - `bin/rails environment db:drop db:structure:load` + rails "environment", "db:drop", "db:structure:load" assert_match expected_database, ActiveRecord::Base.connection_config[:database] require "#{app_path}/app/models/book" #if structure is not loaded correctly, exception would be raised @@ -197,20 +195,18 @@ module ApplicationTests end test "db:structure:dump does not dump schema information when no migrations are used" do - Dir.chdir(app_path) do - # create table without migrations - `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'` + # create table without migrations + rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }" - stderr_output = capture(:stderr) { `bin/rails db:structure:dump` } - assert_empty stderr_output - structure_dump = File.read("db/structure.sql") - assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump) - end + stderr_output = capture(:stderr) { rails("db:structure:dump", stderr: true, allow_failure: true) } + assert_empty stderr_output + structure_dump = File.read("#{app_path}/db/structure.sql") + assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump) end test "db:schema:load and db:structure:load do not purge the existing database" do Dir.chdir(app_path) do - `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'` + rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }" app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: 20140423102712) do @@ -218,17 +214,17 @@ module ApplicationTests end RUBY - list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip } + list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip } assert_equal '["posts"]', list_tables[] - `bin/rails db:schema:load` + rails "db:schema:load" assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[] app_file "db/structure.sql", <<-SQL CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)); SQL - `bin/rails db:structure:load` + rails "db:structure:load" assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[] end end @@ -251,27 +247,25 @@ module ApplicationTests end RUBY - `bin/rails db:schema:load` + rails "db:schema:load" - tables = `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip + tables = rails("runner", "p ActiveRecord::Base.connection.tables").strip assert_match(/"geese"/, tables) - columns = `bin/rails runner 'p ActiveRecord::Base.connection.columns("geese").map(&:name)'`.strip + columns = rails("runner", "p ActiveRecord::Base.connection.columns('geese').map(&:name)").strip assert_equal columns, '["gooseid", "name"]' end end test "db:schema:load fails if schema.rb doesn't exist yet" do - Dir.chdir(app_path) do - stderr_output = capture(:stderr) { `bin/rails db:schema:load` } - assert_match(/Run `rails db:migrate` to create it/, stderr_output) - end + stderr_output = capture(:stderr) { rails("db:schema:load", stderr: true, allow_failure: true) } + assert_match(/Run `rails db:migrate` to create it/, stderr_output) end def db_test_load_structure Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate db:structure:dump db:test:load_structure` + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:structure:dump", "db:test:load_structure" ActiveRecord::Base.configurations = Rails.application.config.database_configuration ActiveRecord::Base.establish_connection :test require "#{app_path}/app/models/book" @@ -307,7 +301,7 @@ module ApplicationTests RUBY Dir.chdir(app_path) do - database_path = `bin/rails db:setup` + database_path = rails("db:setup") assert_equal "development.sqlite3", File.basename(database_path.strip) end ensure diff --git a/railties/test/application/rake/dev_test.rb b/railties/test/application/rake/dev_test.rb index b25593ee1c..66e1ac9d99 100644 --- a/railties/test/application/rake/dev_test.rb +++ b/railties/test/application/rake/dev_test.rb @@ -17,7 +17,7 @@ module ApplicationTests test "dev:cache creates file and outputs message" do Dir.chdir(app_path) do - output = `rails dev:cache` + output = rails("dev:cache") assert File.exist?("tmp/caching-dev.txt") assert_match(/Development mode is now being cached/, output) end @@ -25,8 +25,8 @@ module ApplicationTests test "dev:cache deletes file and outputs message" do Dir.chdir(app_path) do - `rails dev:cache` # Create caching file. - output = `rails dev:cache` # Delete caching file. + rails "dev:cache" # Create caching file. + output = rails("dev:cache") # Delete caching file. assert_not File.exist?("tmp/caching-dev.txt") assert_match(/Development mode is no longer being cached/, output) end @@ -34,12 +34,12 @@ module ApplicationTests test "dev:cache touches tmp/restart.txt" do Dir.chdir(app_path) do - `rails dev:cache` + rails "dev:cache" assert File.exist?("tmp/restart.txt") prev_mtime = File.mtime("tmp/restart.txt") sleep(1) - `rails dev:cache` + rails "dev:cache" curr_mtime = File.mtime("tmp/restart.txt") assert_not_equal prev_mtime, curr_mtime end diff --git a/railties/test/application/rake/log_test.rb b/railties/test/application/rake/log_test.rb index c52be5f396..678f26db26 100644 --- a/railties/test/application/rake/log_test.rb +++ b/railties/test/application/rake/log_test.rb @@ -23,7 +23,7 @@ module ApplicationTests File.write("log/test.log", "test") File.write("log/dummy.log", "dummy") - `rails log:clear` + rails "log:clear" assert_equal 0, File.size("log/test.log") assert_equal 0, File.size("log/staging.log") diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index d130a58441..b0d51eb22e 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -16,21 +16,21 @@ module ApplicationTests test "running migrations with given scope" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string` + rails "generate", "model", "user", "username:string", "password:string" app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION class AMigration < ActiveRecord::Migration::Current end MIGRATION - output = `bin/rails db:migrate SCOPE=bukkits` + output = rails("db:migrate", "SCOPE=bukkits") assert_no_match(/create_table\(:users\)/, output) assert_no_match(/CreateUsers/, output) assert_no_match(/add_column\(:users, :email, :string\)/, output) assert_match(/AMigration: migrated/, output) - output = `bin/rails db:migrate SCOPE=bukkits VERSION=0` + output = rails("db:migrate", "SCOPE=bukkits", "VERSION=0") assert_no_match(/drop_table\(:users\)/, output) assert_no_match(/CreateUsers/, output) assert_no_match(/remove_column\(:users, :email\)/, output) @@ -41,38 +41,38 @@ module ApplicationTests test "migration with empty version" do Dir.chdir(app_path) do - output = `bin/rails db:migrate VERSION= 2>&1` + output = rails("db:migrate", "VERSION=", allow_failure: true) assert_match(/Empty VERSION provided/, output) - output = `bin/rails db:migrate:redo VERSION= 2>&1` + output = rails("db:migrate:redo", "VERSION=", allow_failure: true) assert_match(/Empty VERSION provided/, output) - output = `bin/rails db:migrate:up VERSION= 2>&1` + output = rails("db:migrate:up", "VERSION=", allow_failure: true) assert_match(/VERSION is required/, output) - output = `bin/rails db:migrate:up 2>&1` + output = rails("db:migrate:up", allow_failure: true) assert_match(/VERSION is required/, output) - output = `bin/rails db:migrate:down VERSION= 2>&1` + output = rails("db:migrate:down", "VERSION=", allow_failure: true) assert_match(/VERSION is required - To go down one migration, use db:rollback/, output) - output = `bin/rails db:migrate:down 2>&1` + output = rails("db:migrate:down", allow_failure: true) assert_match(/VERSION is required - To go down one migration, use db:rollback/, output) end end test "model and migration generator with change syntax" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" - output = `bin/rails db:migrate` + output = rails("db:migrate") assert_match(/create_table\(:users\)/, output) assert_match(/CreateUsers: migrated/, output) assert_match(/add_column\(:users, :email, :string\)/, output) assert_match(/AddEmailToUsers: migrated/, output) - output = `bin/rails db:rollback STEP=2` + output = rails("db:rollback", "STEP=2") assert_match(/drop_table\(:users\)/, output) assert_match(/CreateUsers: reverted/, output) assert_match(/remove_column\(:users, :email, :string\)/, output) @@ -81,23 +81,23 @@ module ApplicationTests end test "migration status when schema migrations table is not present" do - output = Dir.chdir(app_path) { `bin/rails db:migrate:status 2>&1` } + output = rails("db:migrate:status", allow_failure: true) assert_equal "Schema migrations table does not exist yet.\n", output end test "migration status" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+Add email to users/, output) - `bin/rails db:rollback STEP=1` - output = `bin/rails db:migrate:status` + rails "db:rollback", "STEP=1" + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/down\s+\d{14}\s+Add email to users/, output) @@ -108,17 +108,17 @@ module ApplicationTests add_to_config("config.active_record.timestamped_migrations = false") Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{3,}\s+Create users/, output) assert_match(/up\s+\d{3,}\s+Add email to users/, output) - `bin/rails db:rollback STEP=1` - output = `bin/rails db:migrate:status` + rails "db:rollback", "STEP=1" + output = rails("db:migrate:status") assert_match(/up\s+\d{3,}\s+Create users/, output) assert_match(/down\s+\d{3,}\s+Add email to users/, output) @@ -127,23 +127,23 @@ module ApplicationTests test "migration status after rollback and redo" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+Add email to users/, output) - `bin/rails db:rollback STEP=2` - output = `bin/rails db:migrate:status` + rails "db:rollback", "STEP=2" + output = rails("db:migrate:status") assert_match(/down\s+\d{14}\s+Create users/, output) assert_match(/down\s+\d{14}\s+Add email to users/, output) - `bin/rails db:migrate:redo` - output = `bin/rails db:migrate:status` + rails "db:migrate:redo" + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+Add email to users/, output) @@ -152,23 +152,23 @@ module ApplicationTests test "migration status after rollback and forward" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+Add email to users/, output) - `bin/rails db:rollback STEP=2` - output = `bin/rails db:migrate:status` + rails "db:rollback", "STEP=2" + output = rails("db:migrate:status") assert_match(/down\s+\d{14}\s+Create users/, output) assert_match(/down\s+\d{14}\s+Add email to users/, output) - `bin/rails db:forward STEP=2` - output = `bin/rails db:migrate:status` + rails "db:forward", "STEP=2" + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+Add email to users/, output) @@ -177,30 +177,30 @@ module ApplicationTests test "raise error on any move when current migration does not exist" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate - rm db/migrate/*email*.rb` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" + `rm db/migrate/*email*.rb` - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output) - output = `bin/rails db:rollback 2>&1` + output = rails("db:rollback", allow_failure: true) assert_match(/rails aborted!/, output) assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output) assert_match(/No migration with version number\s\d{14}\./, output) - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output) - output = `bin/rails db:forward 2>&1` + output = rails("db:forward", allow_failure: true) assert_match(/rails aborted!/, output) assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output) assert_match(/No migration with version number\s\d{14}\./, output) - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output) end @@ -210,23 +210,23 @@ module ApplicationTests add_to_config("config.active_record.timestamped_migrations = false") Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{3,}\s+Create users/, output) assert_match(/up\s+\d{3,}\s+Add email to users/, output) - `bin/rails db:rollback STEP=2` - output = `bin/rails db:migrate:status` + rails "db:rollback", "STEP=2" + output = rails("db:migrate:status") assert_match(/down\s+\d{3,}\s+Create users/, output) assert_match(/down\s+\d{3,}\s+Add email to users/, output) - `bin/rails db:migrate:redo` - output = `bin/rails db:migrate:status` + rails "db:migrate:redo" + output = rails("db:migrate:status") assert_match(/up\s+\d{3,}\s+Create users/, output) assert_match(/up\s+\d{3,}\s+Add email to users/, output) @@ -246,9 +246,9 @@ module ApplicationTests end MIGRATION - `bin/rails db:migrate` + rails "db:migrate" - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+001\s+One migration/, output) assert_match(/up\s+002\s+Two migration/, output) @@ -259,19 +259,19 @@ module ApplicationTests add_to_config("config.active_record.dump_schema_after_migration = false") Dir.chdir(app_path) do - `bin/rails generate model book title:string` - output = `bin/rails generate model author name:string` + rails "generate", "model", "book", "title:string" + output = rails("generate", "model", "author", "name:string") version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1 - `bin/rails db:migrate db:rollback db:forward db:migrate:up db:migrate:down VERSION=#{version}` + rails "db:migrate", "db:rollback", "db:forward", "db:migrate:up", "db:migrate:down", "VERSION=#{version}" assert !File.exist?("db/schema.rb"), "should not dump schema when configured not to" end add_to_config("config.active_record.dump_schema_after_migration = true") Dir.chdir(app_path) do - `bin/rails generate model reviews book_id:integer` - `bin/rails db:migrate` + rails "generate", "model", "reviews", "book_id:integer" + rails "db:migrate" structure_dump = File.read("db/schema.rb") assert_match(/create_table "reviews"/, structure_dump) @@ -280,8 +280,8 @@ module ApplicationTests test "default schema generation after migration" do Dir.chdir(app_path) do - `bin/rails generate model book title:string; - bin/rails db:migrate` + rails "generate", "model", "book", "title:string" + rails "db:migrate" structure_dump = File.read("db/schema.rb") assert_match(/create_table "books"/, structure_dump) @@ -290,12 +290,12 @@ module ApplicationTests test "migration status migrated file is deleted" do Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate migration add_email_to_users email:string; - bin/rails db:migrate - rm db/migrate/*email*.rb` + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "migration", "add_email_to_users", "email:string" + rails "db:migrate" + `rm db/migrate/*email*.rb` - output = `bin/rails db:migrate:status` + output = rails("db:migrate:status") assert_match(/up\s+\d{14}\s+Create users/, output) assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output) diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb index ed96dcb6b1..8614560bf2 100644 --- a/railties/test/application/rake/restart_test.rb +++ b/railties/test/application/rake/restart_test.rb @@ -17,12 +17,12 @@ module ApplicationTests test "rails restart touches tmp/restart.txt" do Dir.chdir(app_path) do - `bin/rails restart` + rails "restart" assert File.exist?("tmp/restart.txt") prev_mtime = File.mtime("tmp/restart.txt") sleep(1) - `bin/rails restart` + rails "restart" curr_mtime = File.mtime("tmp/restart.txt") assert_not_equal prev_mtime, curr_mtime end @@ -31,7 +31,7 @@ module ApplicationTests test "rails restart should work even if tmp folder does not exist" do Dir.chdir(app_path) do FileUtils.remove_dir("tmp") - `bin/rails restart` + rails "restart" assert File.exist?("tmp/restart.txt") end end diff --git a/railties/test/application/rake/tmp_test.rb b/railties/test/application/rake/tmp_test.rb index 8641d140cb..048fd7adcc 100644 --- a/railties/test/application/rake/tmp_test.rb +++ b/railties/test/application/rake/tmp_test.rb @@ -26,7 +26,7 @@ module ApplicationTests FileUtils.mkdir_p("tmp/screenshots") FileUtils.touch("tmp/screenshots/fail.png") - `rails tmp:clear` + rails "tmp:clear" assert_not File.exist?("tmp/cache/cache_file") assert_not File.exist?("tmp/sockets/socket_file") @@ -36,9 +36,7 @@ module ApplicationTests test "tmp:clear should work if folder missing" do FileUtils.remove_dir("#{app_path}/tmp") - errormsg = Dir.chdir(app_path) { `bin/rails tmp:clear` } - assert_predicate $?, :success? - assert_empty errormsg + rails "tmp:clear" end end end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index fe59bed874..f9b14f98cb 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "env_helpers" require "active_support/core_ext/string/strip" module ApplicationTests class RakeTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app @@ -26,20 +27,20 @@ module ApplicationTests end test "task is protected when previous migration was production" do - Dir.chdir(app_path) do - output = `bin/rails generate model product name:string; - env RAILS_ENV=production bin/rails db:create db:migrate; - env RAILS_ENV=production bin/rails db:test:prepare test 2>&1` + with_rails_env "production" do + rails "generate", "model", "product", "name:string" + rails "db:create", "db:migrate" + output = rails("db:test:prepare", allow_failure: true) assert_match(/ActiveRecord::ProtectedEnvironmentError/, output) end end def test_not_protected_when_previous_migration_was_not_production - Dir.chdir(app_path) do - output = `bin/rails generate model product name:string; - env RAILS_ENV=test bin/rails db:create db:migrate; - env RAILS_ENV=test bin/rails db:test:prepare test 2>&1` + with_rails_env "test" do + rails "generate", "model", "product", "name:string" + rails "db:create", "db:migrate" + output = Dir.chdir(app_path) { rails("db:test:prepare", "test") } refute_match(/ActiveRecord::ProtectedEnvironmentError/, output) end @@ -56,7 +57,7 @@ module ApplicationTests Rails.application.initialize! RUBY - assert_match("SuperMiddleware", Dir.chdir(app_path) { `bin/rails middleware` }) + assert_match("SuperMiddleware", rails("middleware")) end def test_initializers_are_executed_in_rake_tasks @@ -71,7 +72,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails do_nothing` } + output = rails("do_nothing") assert_match "Doing something...", output end @@ -92,7 +93,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails do_nothing` } + output = rails("do_nothing") assert_match "Hello world", output end @@ -120,7 +121,7 @@ module ApplicationTests def test_code_statistics_sanity assert_match "Code LOC: 25 Test LOC: 0 Code to Test Ratio: 1:0.0", - Dir.chdir(app_path) { `bin/rails stats` } + rails("stats") end def test_rails_routes_calls_the_route_inspector @@ -130,7 +131,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails routes` } + output = rails("routes") assert_equal <<-MESSAGE.strip_heredoc, output Prefix Verb URI Pattern Controller#Action cart GET /cart(.:format) cart#show @@ -158,7 +159,7 @@ module ApplicationTests " DELETE /post(.:format) posts#destroy", " POST /post(.:format) posts#create\n"].join("\n") - output = Dir.chdir(app_path) { `bin/rails routes -c PostController` } + output = rails("routes", "-c", "PostController") assert_equal expected_output, output end @@ -171,7 +172,7 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails routes -g show` } + output = rails("routes", "-g", "show", allow_failure: true) assert_equal <<-MESSAGE.strip_heredoc, output Prefix Verb URI Pattern Controller#Action cart GET /cart(.:format) cart#show @@ -180,14 +181,14 @@ module ApplicationTests rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show MESSAGE - output = Dir.chdir(app_path) { `bin/rails routes -g POST` } + output = rails("routes", "-g", "POST") assert_equal <<-MESSAGE.strip_heredoc, output Prefix Verb URI Pattern Controller#Action POST /cart(.:format) cart#create rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create MESSAGE - output = Dir.chdir(app_path) { `bin/rails routes -g basketballs` } + output = rails("routes", "-g", "basketballs") assert_equal " Prefix Verb URI Pattern Controller#Action\n" \ "basketballs GET /basketballs(.:format) basketball#index\n", output end @@ -200,13 +201,13 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails routes -c cart` } + output = rails("routes", "-c", "cart") assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output - output = Dir.chdir(app_path) { `bin/rails routes -c Cart` } + output = rails("routes", "-c", "Cart") assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output - output = Dir.chdir(app_path) { `bin/rails routes -c CartController` } + output = rails("routes", "-c", "CartController") assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output end @@ -227,10 +228,10 @@ module ApplicationTests " DELETE /admin/post(.:format) admin/posts#destroy", " POST /admin/post(.:format) admin/posts#create\n"].join("\n") - output = Dir.chdir(app_path) { `bin/rails routes -c Admin::PostController` } + output = rails("routes", "-c", "Admin::PostController") assert_equal expected_output, output - output = Dir.chdir(app_path) { `bin/rails routes -c PostController` } + output = rails("routes", "-c", "PostController") assert_equal expected_output, output end @@ -240,7 +241,7 @@ module ApplicationTests end RUBY - assert_equal <<-MESSAGE.strip_heredoc, Dir.chdir(app_path) { `bin/rails routes` } + assert_equal <<-MESSAGE.strip_heredoc, rails("routes") Prefix Verb URI Pattern Controller#Action rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show rails_blob_variation GET /rails/active_storage/variants/:signed_blob_id/:variation_key/*filename(.:format) active_storage/variants#show @@ -279,43 +280,37 @@ module ApplicationTests end RUBY - output = Dir.chdir(app_path) { `bin/rails log_something RAILS_ENV=production && cat log/production.log` } - assert_match "Sample log message", output + rails "log_something", "RAILS_ENV=production" + assert_match "Sample log message", File.read("#{app_path}/log/production.log") end def test_loading_specific_fixtures - Dir.chdir(app_path) do - `bin/rails generate model user username:string password:string; - bin/rails generate model product name:string; - bin/rails db:migrate` - end + rails "generate", "model", "user", "username:string", "password:string" + rails "generate", "model", "product", "name:string" + rails "db:migrate" require "#{rails_root}/config/environment" # loading a specific fixture - errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load FIXTURES=products` } - assert $?.success?, errormsg + rails "db:fixtures:load", "FIXTURES=products" assert_equal 2, ::AppTemplate::Application::Product.count assert_equal 0, ::AppTemplate::Application::User.count end def test_loading_only_yml_fixtures - Dir.chdir(app_path) do - `bin/rails db:migrate` - end + rails "db:migrate" app_file "test/fixtures/products.csv", "" require "#{rails_root}/config/environment" - errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load` } - assert $?.success?, errormsg + rails "db:fixtures:load" end def test_scaffold_tests_pass_by_default + rails "generate", "scaffold", "user", "username:string", "password:string" output = Dir.chdir(app_path) do - `bin/rails generate scaffold user username:string password:string; - RAILS_ENV=test bin/rails db:migrate test` + `RAILS_ENV=test bin/rails db:migrate test` end assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output) @@ -332,9 +327,9 @@ module ApplicationTests end RUBY + rails "generate", "scaffold", "user", "username:string", "password:string" output = Dir.chdir(app_path) do - `bin/rails generate scaffold user username:string password:string; - RAILS_ENV=test bin/rails db:migrate test` + `RAILS_ENV=test bin/rails db:migrate test` end assert_match(/5 runs, 7 assertions, 0 failures, 0 errors/, output) @@ -342,11 +337,11 @@ module ApplicationTests end def test_scaffold_with_references_columns_tests_pass_by_default + rails "generate", "model", "Product" + rails "generate", "model", "Cart" + rails "generate", "scaffold", "LineItems", "product:references", "cart:belongs_to" output = Dir.chdir(app_path) do - `bin/rails generate model Product; - bin/rails generate model Cart; - bin/rails generate scaffold LineItems product:references cart:belongs_to; - RAILS_ENV=test bin/rails db:migrate test` + `RAILS_ENV=test bin/rails db:migrate test` end assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output) @@ -355,53 +350,45 @@ module ApplicationTests def test_db_test_prepare_when_using_sql_format add_to_config "config.active_record.schema_format = :sql" - output = Dir.chdir(app_path) do - `bin/rails generate scaffold user username:string; - bin/rails db:migrate; - bin/rails db:test:prepare 2>&1 --trace` + rails "generate", "scaffold", "user", "username:string" + rails "db:migrate" + output = with_rails_env("test") do + rails "db:test:prepare", "--trace" end assert_match(/Execute db:test:load_structure/, output) end def test_rake_dump_structure_should_respect_db_structure_env_variable - Dir.chdir(app_path) do - # ensure we have a schema_migrations table to dump - `bin/rails db:migrate db:structure:dump SCHEMA=db/my_structure.sql` - end + # ensure we have a schema_migrations table to dump + rails "db:migrate", "db:structure:dump", "SCHEMA=db/my_structure.sql" assert File.exist?(File.join(app_path, "db", "my_structure.sql")) end def test_rake_dump_structure_should_be_called_twice_when_migrate_redo add_to_config "config.active_record.schema_format = :sql" - output = Dir.chdir(app_path) do - `bin/rails g model post title:string; - bin/rails db:migrate:redo 2>&1 --trace;` - end + rails "g", "model", "post", "title:string" + output = rails("db:migrate:redo", "--trace") # expect only Invoke db:structure:dump (first_time) assert_no_match(/^\*\* Invoke db:structure:dump\s+$/, output) end def test_rake_dump_schema_cache - Dir.chdir(app_path) do - `bin/rails generate model post title:string; - bin/rails generate model product name:string; - bin/rails db:migrate db:schema:cache:dump` - end + rails "generate", "model", "post", "title:string" + rails "generate", "model", "product", "name:string" + rails "db:migrate", "db:schema:cache:dump" assert File.exist?(File.join(app_path, "db", "schema_cache.yml")) end def test_rake_clear_schema_cache - Dir.chdir(app_path) do - `bin/rails db:schema:cache:dump db:schema:cache:clear` - end + rails "db:schema:cache:dump", "db:schema:cache:clear" assert !File.exist?(File.join(app_path, "db", "schema_cache.yml")) end def test_copy_templates Dir.chdir(app_path) do - `bin/rails app:templates:copy` + rails "app:templates:copy" %w(controller mailer scaffold).each do |dir| assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir)) end @@ -415,10 +402,7 @@ module ApplicationTests app_file "config/initializers/dummy.rb", "puts 'Hello, World!'" app_file "template.rb", "" - output = Dir.chdir(app_path) do - `bin/rails app:template LOCATION=template.rb` - end - + output = rails("app:template", "LOCATION=template.rb") assert_match(/Hello, World!/, output) end end diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb index a66f288795..64c46c4b45 100644 --- a/railties/test/application/runner_test.rb +++ b/railties/test/application/runner_test.rb @@ -26,22 +26,19 @@ module ApplicationTests end def test_should_include_runner_in_shebang_line_in_help_without_option - assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner` } + assert_match "/rails runner", rails("runner", allow_failure: true) end def test_should_include_runner_in_shebang_line_in_help - assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner --help` } + assert_match "/rails runner", rails("runner", "--help") end def test_should_run_ruby_statement - assert_match "42", Dir.chdir(app_path) { `bin/rails runner "puts User.count"` } + assert_match "42", rails("runner", "puts User.count") end def test_should_set_argv_when_running_code - output = Dir.chdir(app_path) { - # Both long and short args, at start and end of ARGV - `bin/rails runner "puts ARGV.join(',')" --foo a1 -b a2 a3 --moo` - } + output = rails("runner", "puts ARGV.join(',')", "--foo", "a1", "-b", "a2", "a3", "--moo") assert_equal "--foo,a1,-b,a2,a3,--moo", output.chomp end @@ -50,7 +47,7 @@ module ApplicationTests puts User.count SCRIPT - assert_match "42", Dir.chdir(app_path) { `bin/rails runner "bin/count_users.rb"` } + assert_match "42", rails("runner", "bin/count_users.rb") end def test_no_minitest_loaded_in_production_mode @@ -67,7 +64,7 @@ module ApplicationTests puts $0 SCRIPT - assert_match "bin/dollar0.rb", Dir.chdir(app_path) { `bin/rails runner "bin/dollar0.rb"` } + assert_match "bin/dollar0.rb", rails("runner", "bin/dollar0.rb") end def test_should_set_dollar_program_name_to_file @@ -75,7 +72,7 @@ module ApplicationTests puts $PROGRAM_NAME SCRIPT - assert_match "bin/program_name.rb", Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb"` } + assert_match "bin/program_name.rb", rails("runner", "bin/program_name.rb") end def test_passes_extra_args_to_file @@ -83,7 +80,7 @@ module ApplicationTests p ARGV SCRIPT - assert_match %w( a b ).to_s, Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb" a b` } + assert_match %w( a b ).to_s, rails("runner", "bin/program_name.rb", "a", "b") end def test_should_run_stdin @@ -101,34 +98,34 @@ module ApplicationTests end RUBY - assert_match "true", Dir.chdir(app_path) { `bin/rails runner "puts Rails.application.config.ran"` } + assert_match "true", rails("runner", "puts Rails.application.config.ran") end def test_default_environment - assert_match "development", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` } + assert_match "development", rails("runner", "puts Rails.env") end def test_runner_detects_syntax_errors - output = Dir.chdir(app_path) { `bin/rails runner "puts 'hello world" 2>&1` } + output = rails("runner", "puts 'hello world", allow_failure: true) assert_not $?.success? assert_match "unterminated string meets end of file", output end def test_runner_detects_bad_script_name - output = Dir.chdir(app_path) { `bin/rails runner "iuiqwiourowe" 2>&1` } + output = rails("runner", "iuiqwiourowe", allow_failure: true) assert_not $?.success? assert_match "undefined local variable or method `iuiqwiourowe' for", output end def test_environment_with_rails_env with_rails_env "production" do - assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` } + assert_match "production", rails("runner", "puts Rails.env") end end def test_environment_with_rack_env with_rack_env "production" do - assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` } + assert_match "production", rails("runner", "puts Rails.env") end end end diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index 1eda2a5eaf..e92a0466dd 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -59,7 +59,7 @@ module ApplicationTests def; end RUBY - error = capture(:stderr) { run_test_command("test/models/error_test.rb") } + error = capture(:stderr) { run_test_command("test/models/error_test.rb", stderr: true) } assert_match "syntax error", error end @@ -91,13 +91,11 @@ module ApplicationTests create_test_file :unit, "baz_unit" create_test_file :controllers, "foobar_controller" - Dir.chdir(app_path) do - `bin/rails test:units`.tap do |output| - assert_match "FooTest", output - assert_match "BarHelperTest", output - assert_match "BazUnitTest", output - assert_match "3 runs, 3 assertions, 0 failures", output - end + rails("test:units").tap do |output| + assert_match "FooTest", output + assert_match "BarHelperTest", output + assert_match "BazUnitTest", output + assert_match "3 runs, 3 assertions, 0 failures", output end end @@ -140,13 +138,11 @@ module ApplicationTests create_test_file :functional, "baz_functional" create_test_file :models, "foo" - Dir.chdir(app_path) do - `bin/rails test:functionals`.tap do |output| - assert_match "FooMailerTest", output - assert_match "BarControllerTest", output - assert_match "BazFunctionalTest", output - assert_match "3 runs, 3 assertions, 0 failures", output - end + rails("test:functionals").tap do |output| + assert_match "FooMailerTest", output + assert_match "BarControllerTest", output + assert_match "BazFunctionalTest", output + assert_match "3 runs, 3 assertions, 0 failures", output end end @@ -524,11 +520,11 @@ module ApplicationTests create_test_file :models, "post", pass: false assert_match(/Interrupt/, - capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast") }) + capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast", stderr: true) }) end def test_raise_error_when_specified_file_does_not_exist - error = capture(:stderr) { run_test_command("test/not_exists.rb") } + error = capture(:stderr) { run_test_command("test/not_exists.rb", stderr: true) } assert_match(%r{cannot load such file.+test/not_exists\.rb}, error) end @@ -554,14 +550,16 @@ module ApplicationTests def test_rails_db_create_all_restores_db_connection create_test_file :models, "account" - output = Dir.chdir(app_path) { `bin/rails db:create:all db:migrate && echo ".tables" | rails dbconsole` } + rails "db:create:all", "db:migrate" + output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` } assert_match "ar_internal_metadata", output, "tables should be dumped" end def test_rails_db_create_all_restores_db_connection_after_drop create_test_file :models, "account" - Dir.chdir(app_path) { `bin/rails db:create:all` } # create all to avoid warnings - output = Dir.chdir(app_path) { `bin/rails db:drop:all db:create:all db:migrate && echo ".tables" | rails dbconsole` } + rails "db:create:all" # create all to avoid warnings + rails "db:drop:all", "db:create:all", "db:migrate" + output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` } assert_match "ar_internal_metadata", output, "tables should be dumped" end @@ -601,7 +599,7 @@ module ApplicationTests end RUBY assert_match(/warning: assigned but unused variable/, - capture(:stderr) { run_test_command("test/models/warnings_test.rb -w") }) + capture(:stderr) { run_test_command("test/models/warnings_test.rb -w", stderr: true) }) end def test_reset_sessions_before_rollback_on_system_tests @@ -679,12 +677,12 @@ module ApplicationTests end private - def run_test_command(arguments = "test/unit/test_test.rb") - Dir.chdir(app_path) { `bin/rails t #{arguments}` } + def run_test_command(arguments = "test/unit/test_test.rb", **opts) + rails "t", *Shellwords.split(arguments), allow_failure: true, **opts end def create_model_with_fixture - script "generate model user name:string" + rails "generate", "model", "user", "name:string" app_file "test/fixtures/users.yml", <<-YAML.strip_heredoc vampire: @@ -755,17 +753,17 @@ module ApplicationTests end def create_scaffold - script "generate scaffold user name:string" - Dir.chdir(app_path) { File.exist?("app/models/user.rb") } + rails "generate", "scaffold", "user", "name:string" + assert File.exist?("#{app_path}/app/models/user.rb") run_migration end def create_controller - script "generate controller admin/dashboard index" + rails "generate", "controller", "admin/dashboard", "index" end def run_migration - Dir.chdir(app_path) { `bin/rails db:migrate` } + rails "db:migrate" end end end diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index 7e2364c0a6..0a51e98656 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -102,7 +102,7 @@ module ApplicationTests end test "ruby schema migrations" do - output = script("generate model user name:string") + output = rails("generate", "model", "user", "name:string") version = output.match(/(\d+)_create_users\.rb/)[1] app_file "test/models/user_test.rb", <<-RUBY @@ -139,7 +139,7 @@ module ApplicationTests end test "sql structure migrations" do - output = script("generate model user name:string") + output = rails("generate", "model", "user", "name:string") version = output.match(/(\d+)_create_users\.rb/)[1] app_file "test/models/user_test.rb", <<-RUBY @@ -178,7 +178,7 @@ module ApplicationTests end test "sql structure migrations when adding column to existing table" do - output_1 = script("generate model user name:string") + output_1 = rails("generate", "model", "user", "name:string") version_1 = output_1.match(/(\d+)_create_users\.rb/)[1] app_file "test/models/user_test.rb", <<-RUBY @@ -203,7 +203,7 @@ module ApplicationTests assert_successful_test_run("models/user_test.rb") - output_2 = script("generate migration add_email_to_users") + output_2 = rails("generate", "migration", "add_email_to_users") version_2 = output_2.match(/(\d+)_add_email_to_users\.rb/)[1] app_file "test/models/user_test.rb", <<-RUBY @@ -231,7 +231,7 @@ module ApplicationTests # For now, the user has to synchronize the schema manually. # This test-case serves as a reminder for this use-case. test "manually synchronize test schema after rollback" do - output = script("generate model user name:string") + output = rails("generate", "model", "user", "name:string") version = output.match(/(\d+)_create_users\.rb/)[1] app_file "test/models/user_test.rb", <<-RUBY @@ -265,7 +265,7 @@ module ApplicationTests assert_successful_test_run "models/user_test.rb" - Dir.chdir(app_path) { `bin/rails db:test:prepare` } + rails "db:test:prepare" assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION Expected: ["id", "name"] @@ -274,7 +274,7 @@ Expected: ["id", "name"] end test "hooks for plugins" do - output = script("generate model user name:string") + output = rails("generate", "model", "user", "name:string") version = output.match(/(\d+)_create_users\.rb/)[1] app_file "lib/tasks/hooks.rake", <<-RUBY @@ -334,7 +334,7 @@ Expected: ["id", "name"] end def run_test_file(name, options = {}) - Dir.chdir(app_path) { `bin/rails test "#{app_path}/test/#{name}" 2>&1` } + rails "test", "#{app_path}/test/#{name}", allow_failure: true end end end diff --git a/railties/test/application/version_test.rb b/railties/test/application/version_test.rb index 62d3c7b254..ae85cf8f05 100644 --- a/railties/test/application/version_test.rb +++ b/railties/test/application/version_test.rb @@ -15,12 +15,12 @@ class VersionTest < ActiveSupport::TestCase end test "command works" do - output = Dir.chdir(app_path) { `bin/rails version` } + output = rails("version") assert_equal "Rails #{Rails.gem_version}\n", output end test "short-cut alias works" do - output = Dir.chdir(app_path) { `bin/rails -v` } + output = rails("-v") assert_equal "Rails #{Rails.gem_version}\n", output end end diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb index a1213a57f8..66a81826e3 100644 --- a/railties/test/commands/secrets_test.rb +++ b/railties/test/commands/secrets_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "env_helpers" require "rails/command" require "rails/commands/secrets/secrets_command" class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app @@ -36,14 +37,16 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase private def run_edit_command(editor: "cat") - Dir.chdir(app_path) { `EDITOR="#{editor}" bin/rails secrets:edit` } + switch_env("EDITOR", editor) do + rails "secrets:edit" + end end def run_show_command - Dir.chdir(app_path) { `bin/rails secrets:show` } + rails "secrets:show" end def run_setup_command - Dir.chdir(app_path) { `bin/rails secrets:setup` } + rails "secrets:setup" end end diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 90c366ba17..a4c6fc4e68 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -236,10 +236,88 @@ module TestHelpers end end - def script(script) - Dir.chdir(app_path) do - `#{Gem.ruby} #{app_path}/bin/rails #{script}` + # Invoke a bin/rails command inside the app + # + # allow_failures:: true to return normally if the command exits with + # a non-zero status. By default, this method will raise. + # stderr:: true to pass STDERR output straight to the "real" STDERR. + # By default, the STDERR and STDOUT of the process will be + # combined in the returned string. + # fork:: false to not use fork even when it's available. By default, + # when possible, the command is executed in a fork of the current + # process, avoiding the need to load core Rails libraries anew. + def rails(*args, allow_failure: false, stderr: false, fork: true) + args = args.flatten + + command = "bin/rails #{Shellwords.join args}#{' 2>&1' unless stderr}" + + # Don't fork if the environment has disabled it + fork = false if ENV["NO_FORK"] + + # Don't fork if the runtime isn't able to + fork = false if !Process.respond_to?(:fork) + + # Don't fork if we're re-invoking minitest + fork = false if args.first == "t" || args.grep(/\Atest(:|\z)/).any? + + if fork + out_read, out_write = IO.pipe + if stderr + err_read, err_write = IO.pipe + else + err_write = out_write + end + + pid = fork do + out_read.close + err_read.close if err_read + + $stdin.reopen(File::NULL, "r") + $stdout.reopen(out_write) + $stderr.reopen(err_write) + + at_exit do + case $! + when SystemExit + exit! $!.status + when nil + exit! 0 + else + err_write.puts "#{$!.class}: #{$!}" + exit! 1 + end + end + + Rails.instance_variable_set :@_env, nil + + $-v = $-w = false + Dir.chdir app_path unless Dir.pwd == app_path + + ARGV.replace(args) + load "./bin/rails" + + exit! 0 + end + + out_write.close + + if err_read + err_write.close + + $stderr.write err_read.read + end + + output = out_read.read + + Process.waitpid pid + + else + output = `cd #{app_path}; #{command}` end + + raise "rails command failed (#{$?.exitstatus}): #{command}\n#{output}" unless allow_failure || $?.success? + + output end def add_to_top_of_config(str) diff --git a/railties/test/secrets_test.rb b/railties/test/secrets_test.rb index ff6f955a78..631c6a13fe 100644 --- a/railties/test/secrets_test.rb +++ b/railties/test/secrets_test.rb @@ -108,7 +108,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase config.dereferenced_secret = Rails.application.secrets.some_secret end_of_config - assert_equal "yeah yeah\n", `bin/rails runner -e production "puts Rails.application.config.dereferenced_secret"` + assert_equal "yeah yeah\n", rails("runner", "-e", "production", "puts Rails.application.config.dereferenced_secret", fork: false) end end @@ -141,7 +141,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase assert_match(/production:\n\s*api_key: 00112233445566778899aabbccddeeff…\n/, File.read(tmp_path)) end - assert_equal "00112233445566778899aabbccddeeff…\n", `bin/rails runner -e production "puts Rails.application.secrets.api_key"` + assert_equal "00112233445566778899aabbccddeeff…\n", rails("runner", "-e", "production", "puts Rails.application.secrets.api_key", fork: false) end end @@ -158,7 +158,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase assert_equal(secrets.dup.force_encoding(Encoding::ASCII_8BIT), IO.binread(tmp_path)) end - assert_equal "00112233445566778899aabbccddeeff…\n", `bin/rails runner -e production "puts Rails.application.secrets.api_key"` + assert_equal "00112233445566778899aabbccddeeff…\n", rails("runner", "-e", "production", "puts Rails.application.secrets.api_key", fork: false) end end -- cgit v1.2.3