# frozen_string_literal: true require "isolation/abstract_unit" require "env_helpers" module ApplicationTests class TestRunnerTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app create_schema end def teardown teardown_app end def test_run_via_backwardscompatibility require "minitest/rails_plugin" assert_nothing_raised do Minitest.run_via[:ruby] = true end assert Minitest.run_via[:ruby] end def test_run_single_file create_test_file :models, "foo" create_test_file :models, "bar" assert_match "1 runs, 1 assertions, 0 failures", run_test_command("test/models/foo_test.rb") end def test_run_single_file_with_absolute_path create_test_file :models, "foo" create_test_file :models, "bar" assert_match "1 runs, 1 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb") end def test_run_multiple_files create_test_file :models, "foo" create_test_file :models, "bar" assert_match "2 runs, 2 assertions, 0 failures", run_test_command("test/models/foo_test.rb test/models/bar_test.rb") end def test_run_multiple_files_with_absolute_paths create_test_file :models, "foo" create_test_file :controllers, "foobar_controller" create_test_file :models, "bar" assert_match "2 runs, 2 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb #{app_path}/test/controllers/foobar_controller_test.rb") end def test_run_file_with_syntax_error app_file "test/models/error_test.rb", <<-RUBY require 'test_helper' def; end RUBY error = capture(:stderr) { run_test_command("test/models/error_test.rb", stderr: true) } assert_match "syntax error", error end def test_run_models create_test_file :models, "foo" create_test_file :models, "bar" create_test_file :controllers, "foobar_controller" run_test_command("test/models").tap do |output| assert_match "FooTest", output assert_match "BarTest", output assert_match "2 runs, 2 assertions, 0 failures", output end end def test_run_helpers create_test_file :helpers, "foo_helper" create_test_file :helpers, "bar_helper" create_test_file :controllers, "foobar_controller" run_test_command("test/helpers").tap do |output| assert_match "FooHelperTest", output assert_match "BarHelperTest", output assert_match "2 runs, 2 assertions, 0 failures", output end end def test_run_units create_test_file :models, "foo" create_test_file :helpers, "bar_helper" create_test_file :unit, "baz_unit" create_test_file :controllers, "foobar_controller" 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 def test_run_controllers create_test_file :controllers, "foo_controller" create_test_file :controllers, "bar_controller" create_test_file :models, "foo" run_test_command("test/controllers").tap do |output| assert_match "FooControllerTest", output assert_match "BarControllerTest", output assert_match "2 runs, 2 assertions, 0 failures", output end end def test_run_mailers create_test_file :mailers, "foo_mailer" create_test_file :mailers, "bar_mailer" create_test_file :models, "foo" run_test_command("test/mailers").tap do |output| assert_match "FooMailerTest", output assert_match "BarMailerTest", output assert_match "2 runs, 2 assertions, 0 failures", output end end def test_run_jobs create_test_file :jobs, "foo_job" create_test_file :jobs, "bar_job" create_test_file :models, "foo" run_test_command("test/jobs").tap do |output| assert_match "FooJobTest", output assert_match "BarJobTest", output assert_match "2 runs, 2 assertions, 0 failures", output end end def test_run_functionals create_test_file :mailers, "foo_mailer" create_test_file :controllers, "bar_controller" create_test_file :functional, "baz_functional" create_test_file :models, "foo" 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 def test_run_integration create_test_file :integration, "foo_integration" create_test_file :models, "foo" run_test_command("test/integration").tap do |output| assert_match "FooIntegration", output assert_match "1 runs, 1 assertions, 0 failures", output end end def test_run_all_suites suites = [:models, :helpers, :unit, :controllers, :mailers, :functional, :integration, :jobs] suites.each { |suite| create_test_file suite, "foo_#{suite}" } run_test_command("") .tap do |output| suites.each { |suite| assert_match "Foo#{suite.to_s.camelize}Test", output } assert_match "8 runs, 8 assertions, 0 failures", output end end def test_run_named_test app_file "test/unit/chu_2_koi_test.rb", <<-RUBY require 'test_helper' class Chu2KoiTest < ActiveSupport::TestCase def test_rikka puts 'Rikka' end def test_sanae puts 'Sanae' end end RUBY run_test_command("-n test_rikka test/unit/chu_2_koi_test.rb").tap do |output| assert_match "Rikka", output assert_no_match "Sanae", output end end def test_run_matched_test app_file "test/unit/chu_2_koi_test.rb", <<-RUBY require 'test_helper' class Chu2KoiTest < ActiveSupport::TestCase def test_rikka puts 'Rikka' end def test_sanae puts 'Sanae' end end RUBY run_test_command("-n /rikka/ test/unit/chu_2_koi_test.rb").tap do |output| assert_match "Rikka", output assert_no_match "Sanae", output end end def test_load_fixtures_when_running_test_suites create_model_with_fixture suites = [:models, :helpers, :controllers, :mailers, :integration] suites.each do |suite, directory| directory ||= suite create_fixture_test directory assert_match "3 users", run_test_command("test/#{suite}") Dir.chdir(app_path) { FileUtils.rm_f "test/#{directory}" } end end def test_run_with_model skip "These feel a bit odd. Not sure we should keep supporting them." create_model_with_fixture create_fixture_test "models", "user" assert_match "3 users", run_task(["test models/user"]) assert_match "3 users", run_task(["test app/models/user.rb"]) end def test_run_different_environment_using_env_var skip "no longer possible. Running tests in a different environment should be explicit" app_file "test/unit/env_test.rb", <<-RUBY require 'test_helper' class EnvTest < ActiveSupport::TestCase def test_env puts Rails.env end end RUBY ENV["RAILS_ENV"] = "development" assert_match "development", run_test_command("test/unit/env_test.rb") end def test_run_in_test_environment_by_default create_env_test assert_match "Current Environment: test", run_test_command("test/unit/env_test.rb") end def test_run_different_environment create_env_test assert_match "Current Environment: development", run_test_command("-e development test/unit/env_test.rb") end def test_generated_scaffold_works_with_rails_test create_scaffold assert_match "0 failures, 0 errors, 0 skips", run_test_command("") end def test_generated_controller_works_with_rails_test create_controller assert_match "0 failures, 0 errors, 0 skips", run_test_command("") end def test_run_multiple_folders create_test_file :models, "account" create_test_file :controllers, "accounts_controller" run_test_command("test/models test/controllers").tap do |output| assert_match "AccountTest", output assert_match "AccountsControllerTest", output assert_match "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips", output end end def test_run_multiple_folders_with_absolute_paths create_test_file :models, "account" create_test_file :controllers, "accounts_controller" create_test_file :helpers, "foo_helper" run_test_command("#{app_path}/test/models #{app_path}/test/controllers").tap do |output| assert_match "AccountTest", output assert_match "AccountsControllerTest", output assert_match "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips", output end end def test_run_with_ruby_command app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase test 'declarative syntax works' do puts 'PostTest' assert true end end RUBY Dir.chdir(app_path) do `ruby -Itest test/models/post_test.rb`.tap do |output| assert_match "PostTest", output assert_no_match "is already defined in", output end end end def test_mix_files_and_line_filters create_test_file :models, "account" app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase def test_post puts 'PostTest' assert true end def test_line_filter_does_not_run_this assert true end end RUBY run_test_command("test/models/account_test.rb test/models/post_test.rb:4").tap do |output| assert_match "AccountTest", output assert_match "PostTest", output assert_match "2 runs, 2 assertions", output end end def test_more_than_one_line_filter app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase test "first filter" do puts 'PostTest:FirstFilter' assert true end test "second filter" do puts 'PostTest:SecondFilter' assert true end test "line filter does not run this" do assert true end end RUBY run_test_command("test/models/post_test.rb:4:9").tap do |output| assert_match "PostTest:FirstFilter", output assert_match "PostTest:SecondFilter", output assert_match "2 runs, 2 assertions", output end end def test_more_than_one_line_filter_with_multiple_files app_file "test/models/account_test.rb", <<-RUBY require 'test_helper' class AccountTest < ActiveSupport::TestCase test "first filter" do puts 'AccountTest:FirstFilter' assert true end test "second filter" do puts 'AccountTest:SecondFilter' assert true end test "line filter does not run this" do assert true end end RUBY app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase test "first filter" do puts 'PostTest:FirstFilter' assert true end test "second filter" do puts 'PostTest:SecondFilter' assert true end test "line filter does not run this" do assert true end end RUBY run_test_command("test/models/account_test.rb:4:9 test/models/post_test.rb:4:9").tap do |output| assert_match "AccountTest:FirstFilter", output assert_match "AccountTest:SecondFilter", output assert_match "PostTest:FirstFilter", output assert_match "PostTest:SecondFilter", output assert_match "4 runs, 4 assertions", output end end def test_multiple_line_filters create_test_file :models, "account" create_test_file :models, "post" run_test_command("test/models/account_test.rb:4 test/models/post_test.rb:4").tap do |output| assert_match "AccountTest", output assert_match "PostTest", output end end def test_line_filters_trigger_only_one_runnable app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase test 'truth' do assert true end end class SecondPostTest < ActiveSupport::TestCase test 'truth' do assert false, 'ran second runnable' end end RUBY # Pass seed guaranteeing failure. run_test_command("test/models/post_test.rb:4 --seed 30410").tap do |output| assert_no_match "ran second runnable", output assert_match "1 runs, 1 assertions", output end end def test_line_filter_with_minitest_string_filter app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' class PostTest < ActiveSupport::TestCase test 'by line' do puts 'by line' assert true end test 'by name' do puts 'by name' assert true end end RUBY run_test_command("test/models/post_test.rb:4 -n test_by_name").tap do |output| assert_match "by line", output assert_match "by name", output assert_match "2 runs, 2 assertions", output end end def test_shows_filtered_backtrace_by_default create_backtrace_test assert_match "Rails::BacktraceCleaner", run_test_command("test/unit/backtrace_test.rb") end def test_backtrace_option create_backtrace_test assert_match "Minitest::BacktraceFilter", run_test_command("test/unit/backtrace_test.rb -b") assert_match "Minitest::BacktraceFilter", run_test_command("test/unit/backtrace_test.rb --backtrace") end def test_show_full_backtrace_using_backtrace_environment_variable create_backtrace_test switch_env "BACKTRACE", "true" do assert_match "Minitest::BacktraceFilter", run_test_command("test/unit/backtrace_test.rb") end end def test_run_app_without_rails_loaded # Simulate a real Rails app boot. app_file "config/boot.rb", <<-RUBY ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. RUBY assert_match "0 runs, 0 assertions", run_test_command("") end def test_output_inline_by_default create_test_file :models, "post", pass: false, print: false output = run_test_command("test/models/post_test.rb") expect = %r{Running:\n\nF\n\nFailure:\nPostTest#test_truth \[[^\]]+test/models/post_test.rb:6\]:\nwups!\n\nrails test test/models/post_test.rb:4\n\n\n\n} assert_match expect, output end def test_only_inline_failure_output create_test_file :models, "post", pass: false output = run_test_command("test/models/post_test.rb") assert_match %r{Finished in.*\n1 runs, 1 assertions}, output end def test_fail_fast create_test_file :models, "post", pass: false assert_match(/Interrupt/, capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast", stderr: true) }) end def test_run_in_parallel_with_processes exercise_parallelization_regardless_of_machine_core_count(with: :processes) file_name = create_parallel_processes_test_file app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: 1) do create_table :users do |t| t.string :name end end RUBY output = run_test_command(file_name) assert_match %r{Finished in.*\n2 runs, 2 assertions}, output assert_no_match "create_table(:users)", output end def test_run_in_parallel_with_threads exercise_parallelization_regardless_of_machine_core_count(with: :threads) file_name = create_parallel_threads_test_file app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: 1) do create_table :users do |t| t.string :name end end RUBY output = run_test_command(file_name) assert_match %r{Finished in.*\n2 runs, 2 assertions}, output assert_no_match "create_table(:users)", output end def test_run_in_parallel_with_unmarshable_exception exercise_parallelization_regardless_of_machine_core_count(with: :processes) file = app_file "test/fail_test.rb", <<-RUBY require "test_helper" class FailTest < ActiveSupport::TestCase class BadError < StandardError def initialize super @proc = ->{ } end end test "fail" do raise BadError assert true end end RUBY output = run_test_command(file) assert_match "DRb::DRbRemoteError: FailTest::BadError", output assert_match "1 runs, 0 assertions, 0 failures, 1 errors", output end def test_run_in_parallel_with_unknown_object exercise_parallelization_regardless_of_machine_core_count(with: :processes) create_scaffold app_file "config/environments/test.rb", <<-RUBY Rails.application.configure do config.action_controller.allow_forgery_protection = true config.action_dispatch.show_exceptions = false end RUBY output = run_test_command("-n test_should_create_user") assert_match "ActionController::InvalidAuthenticityToken", output end def test_raise_error_when_specified_file_does_not_exist 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 def test_pass_TEST_env_on_rake_test create_test_file :models, "account" create_test_file :models, "post", pass: false # This specifically verifies TEST for backwards compatibility with rake test # as `rails test` already supports running tests from a single file more cleanly. output = Dir.chdir(app_path) { `bin/rake test TEST=test/models/post_test.rb` } assert_match "PostTest", output, "passing TEST= should run selected test" assert_no_match "AccountTest", output, "passing TEST= should only run selected test" assert_match "1 runs, 1 assertions", output end def test_pass_rake_options create_test_file :models, "account" output = Dir.chdir(app_path) { `bin/rake --rakefile Rakefile --trace=stdout test` } assert_match "1 runs, 1 assertions", output assert_match "Execute test", output end def test_rails_db_create_all_restores_db_connection create_test_file :models, "account" 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" 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 def test_rake_passes_TESTOPTS_to_minitest create_test_file :models, "account" output = Dir.chdir(app_path) { `bin/rake test TESTOPTS=-v` } assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test" end def test_running_with_ruby_gets_test_env_by_default # Subshells inherit `ENV`, so we need to ensure `RAILS_ENV` is set to # nil before we run the tests in the test app. re, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], nil file = create_test_for_env("test") results = Dir.chdir(app_path) { `ruby -Ilib:test #{file}`.each_line.map { |line| JSON.parse line } } assert_equal 1, results.length failures = results.first["failures"] flunk(failures.first) unless failures.empty? ensure ENV["RAILS_ENV"] = re end def test_running_with_ruby_can_set_env_via_cmdline # Subshells inherit `ENV`, so we need to ensure `RAILS_ENV` is set to # nil before we run the tests in the test app. re, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], nil file = create_test_for_env("development") results = Dir.chdir(app_path) { `RAILS_ENV=development ruby -Ilib:test #{file}`.each_line.map { |line| JSON.parse line } } assert_equal 1, results.length failures = results.first["failures"] flunk(failures.first) unless failures.empty? ensure ENV["RAILS_ENV"] = re end def test_rake_passes_multiple_TESTOPTS_to_minitest create_test_file :models, "account" output = Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` } assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test" assert_match "seed=1234", output, "passing TEST= should run selected test" end def test_rake_runs_multiple_test_tasks create_test_file :models, "account" create_test_file :controllers, "accounts_controller" output = Dir.chdir(app_path) { `bin/rake test:models test:controllers TESTOPTS='-v'` } assert_match "AccountTest#test_truth", output assert_match "AccountsControllerTest#test_truth", output end def test_rake_db_and_test_tasks_parses_args_correctly create_test_file :models, "account" output = Dir.chdir(app_path) { `bin/rake db:migrate test:models TESTOPTS='-v' && echo ".tables" | rails dbconsole` } assert_match "AccountTest#test_truth", output assert_match "ar_internal_metadata", output end def test_warnings_option app_file "test/models/warnings_test.rb", <<-RUBY require 'test_helper' def test_warnings a = 1 end RUBY assert_match(/warning: assigned but unused variable/, capture(:stderr) { run_test_command("test/models/warnings_test.rb -w", stderr: true) }) end def test_reset_sessions_before_rollback_on_system_tests app_file "test/system/reset_session_before_rollback_test.rb", <<-RUBY require "application_system_test_case" class ResetSessionBeforeRollbackTest < ApplicationSystemTestCase def teardown_fixtures puts "rollback" super end Capybara.singleton_class.prepend(Module.new do def reset_sessions! puts "reset sessions" super end end) test "dummy" do end end RUBY run_test_command("test/system/reset_session_before_rollback_test.rb").tap do |output| assert_match "reset sessions\nrollback", output assert_match "1 runs, 0 assertions, 0 failures, 0 errors, 0 skips", output end end def test_reset_sessions_on_failed_system_test_screenshot app_file "test/system/reset_sessions_on_failed_system_test_screenshot_test.rb", <<~RUBY require "application_system_test_case" class ResetSessionsOnFailedSystemTestScreenshotTest < ApplicationSystemTestCase ActionDispatch::SystemTestCase.class_eval do def take_failed_screenshot raise Capybara::CapybaraError end end Capybara.instance_eval do def reset_sessions! puts "Capybara.reset_sessions! called" end end test "dummy" do end end RUBY output = run_test_command("test/system/reset_sessions_on_failed_system_test_screenshot_test.rb") assert_match "Capybara.reset_sessions! called", output end def test_system_tests_are_not_run_with_the_default_test_command app_file "test/system/dummy_test.rb", <<-RUBY require "application_system_test_case" class DummyTest < ApplicationSystemTestCase test "something" do assert true end end RUBY run_test_command("").tap do |output| assert_match "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips", output end end def test_system_tests_are_not_run_through_rake_test app_file "test/system/dummy_test.rb", <<-RUBY require "application_system_test_case" class DummyTest < ApplicationSystemTestCase test "something" do assert true end end RUBY output = Dir.chdir(app_path) { `bin/rake test` } assert_match "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips", output end def test_system_tests_are_run_through_rake_test_when_given_in_TEST app_file "test/system/dummy_test.rb", <<-RUBY require "application_system_test_case" class DummyTest < ApplicationSystemTestCase test "something" do assert true end end RUBY output = Dir.chdir(app_path) { `bin/rake test TEST=test/system/dummy_test.rb` } assert_match "1 runs, 1 assertions, 0 failures, 0 errors, 0 skips", output end private 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 rails "generate", "model", "user", "name:string" app_file "test/fixtures/users.yml", <<~YAML vampire: id: 1 name: Koyomi Araragi crab: id: 2 name: Senjougahara Hitagi cat: id: 3 name: Tsubasa Hanekawa YAML run_migration end def create_fixture_test(path = :unit, name = "test") app_file "test/#{path}/#{name}_test.rb", <<-RUBY require 'test_helper' class #{name.camelize}Test < ActiveSupport::TestCase def test_fixture puts "\#{User.count} users (\#{__FILE__})" end end RUBY end def create_backtrace_test app_file "test/unit/backtrace_test.rb", <<-RUBY require 'test_helper' class BacktraceTest < ActiveSupport::TestCase def test_backtrace puts Minitest.backtrace_filter end end RUBY end def create_schema app_file "db/schema.rb", "" end def create_test_for_env(env) app_file "test/models/environment_test.rb", <<-RUBY require 'test_helper' class JSONReporter < Minitest::AbstractReporter def record(result) puts JSON.dump(klass: result.class.name, name: result.name, failures: result.failures, assertions: result.assertions, time: result.time) end end def Minitest.plugin_json_reporter_init(opts) Minitest.reporter.reporters.clear Minitest.reporter.reporters << JSONReporter.new end Minitest.extensions << "rails" Minitest.extensions << "json_reporter" # Minitest uses RubyGems to find plugins, and since RubyGems # doesn't know about the Rails installation we're pointing at, # Minitest won't require the Rails minitest plugin when we run # these integration tests. So we have to manually require the # Minitest plugin here. require 'minitest/rails_plugin' class EnvironmentTest < ActiveSupport::TestCase def test_environment test_db = ActiveRecord::Base.configurations[#{env.dump}]["database"] db_file = ActiveRecord::Base.connection_config[:database] assert_match(test_db, db_file) assert_equal #{env.dump}, ENV["RAILS_ENV"] end end RUBY end def create_test_file(path = :unit, name = "test", pass: true, print: true) app_file "test/#{path}/#{name}_test.rb", <<-RUBY require 'test_helper' class #{name.camelize}Test < ActiveSupport::TestCase def test_truth puts "#{name.camelize}Test" if #{print} assert #{pass}, 'wups!' end end RUBY end def create_parallel_processes_test_file app_file "test/models/parallel_test.rb", <<-RUBY require 'test_helper' class ParallelTest < ActiveSupport::TestCase RD1, WR1 = IO.pipe RD2, WR2 = IO.pipe test "one" do WR1.close assert_equal "x", RD1.read(1) # blocks until two runs RD2.close WR2.write "y" # Allow two to run WR2.close end test "two" do RD1.close WR1.write "x" # Allow one to run WR1.close WR2.close assert_equal "y", RD2.read(1) # blocks until one runs end end RUBY end def create_parallel_threads_test_file app_file "test/models/parallel_test.rb", <<-RUBY require 'test_helper' class ParallelTest < ActiveSupport::TestCase Q1 = Queue.new Q2 = Queue.new test "one" do assert_equal "x", Q1.pop # blocks until two runs Q2 << "y" end test "two" do Q1 << "x" assert_equal "y", Q2.pop # blocks until one runs end end RUBY end def exercise_parallelization_regardless_of_machine_core_count(with:) app_path("test/test_helper.rb") do |file_name| file = File.read(file_name) file.sub!(/parallelize\(([^\)]*)\)/, "parallelize(workers: 2, with: :#{with})") File.write(file_name, file) end end def create_env_test app_file "test/unit/env_test.rb", <<-RUBY require 'test_helper' class EnvTest < ActiveSupport::TestCase def test_env puts "Current Environment: \#{Rails.env}" end end RUBY end def create_scaffold rails "generate", "scaffold", "user", "name:string" assert File.exist?("#{app_path}/app/models/user.rb") run_migration end def create_controller rails "generate", "controller", "admin/dashboard", "index" end def run_migration rails "db:migrate" end end end