-
-
Save hernan/f384a2ad52d9544faa39fe5f340d491a to your computer and use it in GitHub Desktop.
Rails 6 parallel minitest with sqlite3 :memory: databases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#### evals the schema into the current process | |
class SqliteTestDbLoader | |
# assumes your schema is generated for MySQL | |
# tweak for Postgres! | |
MYSQL_REPLACEMENTS = { | |
/ENGINE=InnoDB DEFAULT CHARSET=[a-z0-9]*/ => '', | |
/, collation: "[^"]*"/ => '' | |
} | |
class << self | |
def reload!(context) | |
new.reload! | |
ensure | |
# puts "Reloaded Schema: #{context}" | |
end | |
end | |
# grab schema from fs | |
def extract | |
File.read( | |
Rails.root.join( | |
"db", "schema.rb")) | |
end | |
# Get rid of non-standard SQL unimportables | |
def transform(schema) | |
MYSQL_REPLACEMENTS | |
.reduce(schema) do |res, replacement| | |
res.gsub(*replacement) | |
end | |
end | |
# load into sqlite's :memory: db | |
def load(schema) | |
eval(schema) | |
end | |
def reload! ; load(transform(extract)) ; end | |
end | |
# Always load schema into :memory: after a new connection | |
module SqlitePostConnectionLoad | |
def establish_connection(*args, &block) | |
super | |
connection | |
.migration_context | |
.needs_migration? && | |
SqliteTestDbLoader.reload!("#{self.class.name}#establish_connection") | |
end | |
end | |
# "rails/test_help" needs a connection early on in the test_helper load process | |
module CheckPendingSoftly | |
def check_pending!(conn = ActiveRecord::Base.connection) | |
conn | |
.migration_context | |
.needs_migration? | |
.yield_self do |needs_migration| | |
needs_migration && | |
SqliteTestDbLoader.reload!("#{self.class.name}#check_pending!") | |
end | |
end | |
end | |
module PreserveParallelMemoryDatabase | |
def create_and_load_schema(i, env_name:) | |
if ActiveRecord::Base | |
.configurations | |
.configs_for(env_name: env_name) | |
.to_s.match(/:memory:/m) | |
puts "Memory database found. Skipping db creation" | |
ActiveRecord::Base.establish_connection(Rails.env.to_sym) | |
return | |
end | |
super | |
end | |
end | |
ActiveSupport.on_load(:active_record) do | |
ActiveRecord::Migration.singleton_class.prepend CheckPendingSoftly | |
ActiveRecord::TestDatabases.singleton_class.prepend PreserveParallelMemoryDatabase | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ENV['RAILS_ENV'] ||= 'test' | |
require_relative '../config/environment' | |
# must load BEFORE rails/test_help | |
require_relative './support/sqlite_test_db_loader.rb' | |
require 'rails/test_help' | |
require "minitest/rails" | |
# This assumes you're sharing config between unit/integration | |
module TestSetup | |
extend ActiveSupport::Concern | |
included do | |
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. | |
fixtures :all | |
# Use Jest-like CI flag | |
parallelize(workers: ENV['CI'] ? 1 : :number_of_processors, with: :processes) | |
# Make sure that you reload the sqlite when starting processes | |
parallelize_setup do | |
# slightly more efficient than a direct call to establish_connection | |
ActiveRecord::Migration.check_pending! | |
end | |
end | |
end | |
class ActiveSupport::TestCase | |
include TestSetup | |
end | |
class ActionDispatch::IntegrationTest | |
include TestSetup | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment