Ответ вернулся в список рассылки о том, что это в основном ситуация «сделай сам», поэтому, чтобы избавить других от хлопот, если им в конечном итоге придется сделать это тоже:
Создайте файл .rake в lib / tasks, который называется что-то вроде test_db_setup.rake:
require File.dirname(__FILE__) + '/../../test/database_dumper'
# Custom logic that runs before the test suite begins
# This just clones the development database schema to the test database
# Note that each test does a lightweight teardown of just truncating all tables
namespace :db do
namespace :test do
desc "Reset the test database to match the development schema"
task :prepare do
Rake::Task['db:schema:clone'].invoke
end
end
namespace :schema do
desc "Literally dump the database schema into db/schema/**/*.sql"
task :dump => :environment do
DatabaseDumper.dump_schema(:directory => "#{Rails.root}/db/schema", :env => Rails.env)
end
desc "Clones the development schema into the test database"
task :clone => [:dump, :environment] do
DatabaseDumper.import_schema(:directory => "#{Rails.root}/db/schema", :env => "test")
end
end
end
task 'test:prepare' => 'db:test:prepare'
Используется хук :test:prepare
, предоставляемый Rails, который запускается непосредственно перед началом набора тестов. Он копирует схему из вашей базы данных разработки в файлы .sql в каталоге db / schema / (по одному на таблицу / представление), а затем импортирует эти файлы .sql в вашу тестовую базу данных.
Для этого вам понадобится служебный класс, который я написал (в настоящее время он написан для MySQL> = 5.0.1. Вам придется настроить логику, если вам нужна другая база данных.
# Utility class for dumping and importing the database schema
class DatabaseDumper
def self.dump_schema(options = {})
options[:directory] ||= "#{Rails.root}/db/schema"
options[:env] ||= Rails.env
schema_dir = options[:directory]
clean_sql_directory(schema_dir)
Rails::DataMapper.configuration.repositories[options[:env]].each do |repository, config|
repository_dir = "#{schema_dir}/#{repository}"
adapter = DataMapper.setup(repository, config)
perform_schema_dump(adapter, repository_dir)
end
end
def self.import_schema(options = {})
options[:directory] ||= "#{Rails.root}/db/schema"
options[:env] ||= "test"
schema_dir = options[:directory]
Rails::DataMapper.configuration.repositories[options[:env]].each do |repository, config|
repository_dir = "#{schema_dir}/#{repository}"
adapter = DataMapper.setup(repository, config)
perform_schema_import(adapter, repository_dir)
end
end
private
def self.clean_sql_directory(path)
Dir.mkdir(path) unless Dir.exists?(path)
Dir.glob("#{path}/**/*.sql").each do |file|
File.delete(file)
end
end
def self.perform_schema_dump(adapter, path)
Dir.mkdir(path) unless Dir.exists?(path)
adapter.select("SHOW FULL TABLES").each do |row|
name = row.values.first
type = row.values.last
sql_dir = "#{path}/#{directory_name_for_table_type(type)}"
Dir.mkdir(sql_dir) unless Dir.exists?(sql_dir)
schema_info = adapter.select("SHOW CREATE TABLE #{name}").first
sql = schema_info.values.last
f = File.open("#{sql_dir}/#{name}.sql", "w+")
f << sql << "\n"
f.close
end
end
def self.directory_name_for_table_type(type)
case type
when "VIEW"
"views"
when "BASE TABLE"
"tables"
else
raise "Unknown table type #{type}"
end
end
def self.perform_schema_import(adapter, path)
tables_dir = "#{path}/tables"
views_dir = "#{path}/views"
{ "TABLE" => tables_dir, "VIEW" => views_dir }.each do |type, sql_dir|
Dir.glob("#{sql_dir}/*.sql").each do |file|
name = File.basename(file, ".sql")
drop_sql = "DROP #{type} IF EXISTS `#{name}`"
create_sql = File.open(file, "r").read
adapter.execute(drop_sql)
adapter.execute(create_sql)
end
end
end
end
Это также оставит файлы .sql в вашем каталоге схемы, поэтому вы можете просматривать их, если вам нужна ссылка.
Теперь это приведет к стиранию вашей базы данных (путем установки новой схемы) при запуске набора тестов. Это не сотрет тесты между методами испытаний. Для этого вы захотите использовать DatabaseCleaner . Поместите это в свой test_helper.rb:
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation, {:except => %w(auctionindexview helpindexview)}
class ActiveSupport::TestCase
setup :setup_database
teardown :clean_database
private
def setup_database
DatabaseCleaner.start
end
def clean_database
DatabaseCleaner.clean
end
end
Теперь тебе надо идти. Ваша схема будет свежа, когда вы начнете выполнять тесты, у вас будет копия SQL в каталоге db / schema, и ваши данные будут стерты между методами тестирования. Предупреждение, если вы соблазнены стратегией транзакций DatabaseCleaner ... это редко безопасная стратегия для использования в MySQL, поскольку ни один из типов таблиц MySQL в настоящее время не поддерживает вложенные транзакции, поэтому логика вашего приложения, скорее всего, сломает демонтаж , Усечение по-прежнему быстрое и намного безопаснее.