Permalink
Browse files

Add multidb application test

I realized I wasn't really testing some of the new rake tasks added so I
built out this new test that uses a multi-db database.yml and allows us
to run create/drop/migrate/schema:dump/schema:load and those that are
namespaced like create:animals. This will make our testing more robust
so we can catch problems quicker and set a good place to add future
tests as these features evolve.
  • Loading branch information...
eileencodes committed Apr 6, 2018
1 parent 48d5849 commit fa5a028ed9fccf54bb320e6a99a5a539de4c57ba
Showing with 215 additions and 16 deletions.
  1. +164 −0 railties/test/application/rake/multi_dbs_test.rb
  2. +51 −16 railties/test/isolation/abstract_unit.rb
@@ -0,0 +1,164 @@
# frozen_string_literal: true
require "isolation/abstract_unit"
module ApplicationTests
module RakeTests
class RakeMultiDbsTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
def setup
build_app(multi_db: true)
FileUtils.rm_rf("#{app_path}/config/environments")
end
def teardown
teardown_app
end
def db_create_and_drop(namespace, expected_database, environment_loaded: true)
Dir.chdir(app_path) do
output = rails("db:create")
assert_match(/Created database/, output)
assert_match_namespace(namespace, output)
assert File.exist?(expected_database)
output = rails("db:drop")
assert_match(/Dropped database/, output)
assert_match_namespace(namespace, output)
assert !File.exist?(expected_database)
end
end
def db_create_and_drop_namespace(namespace, expected_database, environment_loaded: true)
Dir.chdir(app_path) do
output = rails("db:create:#{namespace}")
assert_match(/Created database/, output)
assert_match_namespace(namespace, output)
assert File.exist?(expected_database)
output = rails("db:drop:#{namespace}")
assert_match(/Dropped database/, output)
assert_match_namespace(namespace, output)
assert !File.exist?(expected_database)
end
end
def assert_match_namespace(namespace, output)
if namespace == "primary"
assert_match(/#{Rails.env}.sqlite3/, output)
else
assert_match(/#{Rails.env}_#{namespace}.sqlite3/, output)
end
end
def db_migrate_and_schema_dump_and_load(namespace, expected_database, format)
Dir.chdir(app_path) do
rails "generate", "model", "book", "title:string"
rails "generate", "model", "dog", "name:string"
write_models_for_animals
rails "db:migrate", "db:#{format}:dump"
if format == "schema"
schema_dump = File.read("db/#{format}.rb")
schema_dump_animals = File.read("db/animals_#{format}.rb")
assert_match(/create_table \"books\"/, schema_dump)
assert_match(/create_table \"dogs\"/, schema_dump_animals)
else
schema_dump = File.read("db/#{format}.sql")
schema_dump_animals = File.read("db/animals_#{format}.sql")
assert_match(/CREATE TABLE \"books\"/, schema_dump)
assert_match(/CREATE TABLE \"dogs\"/, schema_dump_animals)
end
rails "db:#{format}:load"
ar_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
animals_tables = lambda { rails("runner", "p AnimalsBase.connection.tables").strip }
assert_equal '["schema_migrations", "ar_internal_metadata", "books"]', ar_tables[]
assert_equal '["schema_migrations", "ar_internal_metadata", "dogs"]', animals_tables[]
end
end
def db_migrate_namespaced(namespace, expected_database)
Dir.chdir(app_path) do
rails "generate", "model", "book", "title:string"
rails "generate", "model", "dog", "name:string"
write_models_for_animals
output = rails("db:migrate:#{namespace}")
if namespace == "primary"
assert_match(/CreateBooks: migrated/, output)
else
assert_match(/CreateDogs: migrated/, output)
end
end
end
def write_models_for_animals
# make a directory for the animals migration
FileUtils.mkdir_p("#{app_path}/db/animals_migrate")
# move the dogs migration if it unless it already lives there
FileUtils.mv(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first, "db/animals_migrate/") unless Dir.glob("#{app_path}/db/animals_migrate/**/*dogs.rb").first
# delete the dogs migration if it's still present in the
# migrate folder. This is necessary because sometimes
# the code isn't fast enough and an extra migration gets made
FileUtils.rm(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first) if Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first
# change the base of the dog model
app_path("/app/models/dog.rb") do |file_name|
file = File.read("#{app_path}/app/models/dog.rb")
file.sub!(/ApplicationRecord/, "AnimalsBase")
File.write(file_name, file)
end
# create the base model for dog to inherit from
File.open("#{app_path}/app/models/animals_base.rb", "w") do |file|
file.write(<<-EOS
class AnimalsBase < ActiveRecord::Base
self.abstract_class = true
establish_connection :animals
end
EOS
)
end
end
test "db:create and db:drop works on all databases for env" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
db_create_and_drop namespace, config["database"]
end
end
test "db:create:namespace and db:drop:namespace works on specified databases" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
db_create_and_drop_namespace namespace, config["database"]
end
end
test "db:migrate and db:schema:dump and db:schema:load works on all databases" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
db_migrate_and_schema_dump_and_load namespace, config["database"], "schema"
end
end
test "db:migrate and db:structure:dump and db:structure:load works on all databases" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
db_migrate_and_schema_dump_and_load namespace, config["database"], "structure"
end
end
test "db:migrate:namespace works" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
db_migrate_namespaced namespace, config["database"]
end
end
end
end
end
@@ -112,22 +112,57 @@ def build_app(options = {})
end
end
File.open("#{app_path}/config/database.yml", "w") do |f|
f.puts <<-YAML
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
YAML
if options[:multi_db]
File.open("#{app_path}/config/database.yml", "w") do |f|
f.puts <<-YAML
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
primary:
<<: *default
database: db/development.sqlite3
animals:
<<: *default
database: db/development_animals.sqlite3
migrations_paths: db/animals_migrate
test:
primary:
<<: *default
database: db/test.sqlite3
animals:
<<: *default
database: db/test_animals.sqlite3
migrations_paths: db/animals_migrate
production:
primary:
<<: *default
database: db/production.sqlite3
animals:
<<: *default
database: db/production_animals.sqlite3
migrations_paths: db/animals_migrate
YAML
end
else
File.open("#{app_path}/config/database.yml", "w") do |f|
f.puts <<-YAML
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
YAML
end
end
add_to_config <<-RUBY

0 comments on commit fa5a028

Please sign in to comment.