Make Rails 6 integration tests faster

This commit is contained in:
Elliot Winkler 2020-08-23 21:55:46 -06:00
parent 97b97015f4
commit 4dab96cdb1
8 changed files with 134 additions and 69 deletions

View File

@ -4,7 +4,7 @@ require 'rspec/core/rake_task'
require 'appraisal'
require_relative 'tasks/documentation'
require_relative 'spec/support/tests/database'
require_relative 'spec/support/tests/current_bundle'
require_relative 'support/current_bundle'
RSpec::Core::RakeTask.new('spec:unit') do |t|
t.ruby_opts = '-w -r ./spec/report_warnings'
@ -21,14 +21,14 @@ RSpec::Core::RakeTask.new('spec:acceptance') do |t|
end
task :default do
if Tests::CurrentBundle.instance.appraisal_in_use?
if Shoulda::Matchers::CurrentBundle.instance.appraisal_in_use?
sh 'rake spec:unit --trace'
sh 'rake spec:acceptance --trace'
else
if ENV['CI']
exec "appraisal install && appraisal rake --trace"
else
appraisal = Tests::CurrentBundle.instance.latest_appraisal
appraisal = Shoulda::Matchers::CurrentBundle.instance.latest_appraisal
exec "appraisal install && appraisal #{appraisal} rake --trace"
end
end
@ -36,7 +36,7 @@ end
namespace :appraisal do
task :list do
appraisals = Tests::CurrentBundle.instance.available_appraisals
appraisals = Shoulda::Matchers::CurrentBundle.instance.available_appraisals
puts "Valid appraisals: #{appraisals.join(', ')}"
end
end

9
bin/rspec Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env ruby
require_relative '../support/current_bundle'
current_bundle = Shoulda::Matchers::CurrentBundle.instance
ENV['BUNDLE_GEMFILE'] ||= current_bundle.latest_appraisal.gemfile_path.to_s
exec('bundle', 'exec', 'rspec', *ARGV)

View File

@ -1,6 +1,6 @@
require 'zeus'
require 'zeus/plan'
require_relative 'spec/support/tests/current_bundle'
require_relative 'support/current_bundle'
class CouldNotBootZeusError < StandardError
def self.create(underlying_error:)
@ -64,7 +64,7 @@ class CustomPlan < Zeus::Plan
end
def current_bundle
Tests::CurrentBundle.instance
Shoulda::Matchers::CurrentBundle.instance
end
def file_paths_to_run

View File

@ -1,6 +1,6 @@
require_relative 'support/tests/current_bundle'
require_relative '../support/current_bundle'
Tests::CurrentBundle.instance.assert_appraisal!
Shoulda::Matchers::CurrentBundle.instance.assert_appraisal!
#---

View File

@ -58,13 +58,37 @@ module AcceptanceTests
def create_rails_application
fs.clean
options = [
'--no-rc',
'--skip-bundle',
'--skip-javascript',
'--skip-listen',
'--skip-spring',
'--skip-sprockets',
'--skip-turbolinks',
]
if rails_version =~ '~> 6.0'
command = "bundle exec rails new #{fs.project_directory} --skip-bundle --skip-javascript --no-rc"
else
command = "bundle exec rails new #{fs.project_directory} --skip-bundle --no-rc"
options += [
'--skip-action-cable',
'--skip-action-mailbox',
'--skip-action-text',
'--skip-bootsnap',
'--skip-webpack-install',
]
end
run_command!(command) do |runner|
command = [
'bundle',
'exec',
'rails',
'new',
fs.project_directory.to_s,
*options,
]
run_command!(*command) do |runner|
runner.directory = nil
end

View File

@ -1,55 +0,0 @@
require 'bundler'
require 'appraisal'
module Tests
class CurrentBundle
AppraisalNotSpecified = Class.new(ArgumentError)
include Singleton
def assert_appraisal!
unless appraisal_in_use?
message = <<EOT
Please run tests starting with `appraisal <appraisal_name>`.
Possible appraisals are: #{available_appraisals}
EOT
raise AppraisalNotSpecified, message
end
end
def appraisal_in_use?
path.dirname == root.join('gemfiles')
end
def current_or_latest_appraisal
current_appraisal || latest_appraisal
end
def latest_appraisal
available_appraisals.sort.last
end
def available_appraisals
Appraisal::AppraisalFile.each.map(&:name)
end
private
def current_appraisal
if appraisal_in_use?
File.basename(path, ".gemfile")
end
end
def path
Bundler.default_gemfile
end
def root
Pathname.new('../../../..').expand_path(__FILE__)
end
end
end

View File

@ -1,7 +1,7 @@
require_relative '../tests/current_bundle'
require_relative '../support/current_bundle'
require_relative 'rails_application'
Tests::CurrentBundle.instance.assert_appraisal!
Shoulda::Matchers::CurrentBundle.instance.assert_appraisal!
$test_app = UnitTests::RailsApplication.new
$test_app.create

87
support/current_bundle.rb Normal file
View File

@ -0,0 +1,87 @@
require "bundler"
require "shellwords"
require "singleton"
module Shoulda
module Matchers
class CurrentBundle
include Singleton
ROOT_DIR = Pathname.new("..").expand_path(__dir__)
APPRAISAL_GEMFILES_PATH = ROOT_DIR.join("gemfiles")
def assert_appraisal!
unless appraisal_in_use?
raise AppraisalNotSpecified.new(<<~MESSAGE)
Please run tests by specifying an appraisal, like:
bundle exec appraisal <appraisal_name> #{current_command}
Possible appraisals are:
#{available_appraisals.map { |appraisal| " - #{appraisal.name}" }.join("\n")}
Or to simply go with the latest appraisal, use:
bin/rspec #{shell_arguments}
MESSAGE
end
end
def appraisal_in_use?
!current_appraisal.nil?
end
def current_appraisal
if path
available_appraisals.find do |appraisal|
appraisal.gemfile_path.to_s == path.to_s
end
else
nil
end
end
def latest_appraisal
available_appraisals.max_by(&:name)
end
private
def path
Bundler.default_gemfile
end
def available_appraisals
@_available_appraisals ||= Dir.glob(
APPRAISAL_GEMFILES_PATH.join("*.gemfile").to_s,
).
map do |path|
FakeAppraisal.new(
name: File.basename(path).sub(/\.gemfile$/, ""),
gemfile_path: path,
)
end
end
def current_command
Shellwords.join([File.basename($0)] + ARGV)
end
def shell_arguments
Shellwords.join(ARGV)
end
class FakeAppraisal
attr_reader :name, :gemfile_path
def initialize(name:, gemfile_path:)
@name = name
@gemfile_path = gemfile_path
end
end
class AppraisalNotSpecified < ArgumentError; end
end
end
end