Fix Rails environment when running tests with Ruby

I frequently run tests with `ruby`, not with a runner like `rake` or
`rails`.  When running the test with just `ruby` the `RAILS_ENV`
environment variable did not get set to "test", and this would cause the
tests to fail (and even mutate the development database!)

This commit adds integration tests for running tests with just `ruby`
and ensures the environment gets defaulted to "test".  I also added a
test to ensure that passing an environment to `-e` actually works (and
fixed that case too).

An interesting / annoying thing is that Minitest picks up it's plugins
by asking RubyGems for a list of files:

  https://github.com/seattlerb/minitest/blob/ca6a71ca901016db09a5ad466b4adea4b52a504a/lib/minitest.rb#L92-L100

This means that RubyGems needs to somehow know about the file before it
can return it to Minitest.  Since we are not packaging Rails as a Gem
before running the integration tests on it (duh, why would you do
that?), RubyGems doesn't know about the file, so it can't tell Minitest,
so Minitest doesn't automatically require it.  This means I had to
manually require and insert the plugin in our integration test.  I've
left comments about that in the test as well.

Ugh.
上级 0ba5615e
...@@ -12,8 +12,11 @@ class Runner ...@@ -12,8 +12,11 @@ class Runner
class << self class << self
def attach_before_load_options(opts) def attach_before_load_options(opts)
ENV["RAILS_ENV"] = "test"
opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {} opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {}
opts.on("--environment", "-e", "Run tests in the ENV environment") {} opts.on("-e", "--environment ENV", "Run tests in the ENV environment") { |e|
ENV["RAILS_ENV"] = e
}
end end
def parse_options(argv) def parse_options(argv)
......
...@@ -569,6 +569,26 @@ def test_rake_passes_TESTOPTS_to_minitest ...@@ -569,6 +569,26 @@ def test_rake_passes_TESTOPTS_to_minitest
assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test" assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test"
end end
def test_running_with_ruby_gets_test_env_by_default
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?
end
def test_running_with_ruby_can_set_env_via_cmdline
file = create_test_for_env("development")
results = Dir.chdir(app_path) {
`ruby -Ilib:test #{file} -e development`.each_line.map { |line| JSON.parse line }
}
assert_equal 1, results.length
failures = results.first["failures"]
flunk(failures.first) unless failures.empty?
end
def test_rake_passes_multiple_TESTOPTS_to_minitest def test_rake_passes_multiple_TESTOPTS_to_minitest
create_test_file :models, "account" create_test_file :models, "account"
output = Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` } output = Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` }
...@@ -727,6 +747,42 @@ def create_schema ...@@ -727,6 +747,42 @@ def create_schema
app_file "db/schema.rb", "" app_file "db/schema.rb", ""
end 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
assert_equal #{env.dump}, ENV["RAILS_ENV"]
end
end
RUBY
end
def create_test_file(path = :unit, name = "test", pass: true) def create_test_file(path = :unit, name = "test", pass: true)
app_file "test/#{path}/#{name}_test.rb", <<-RUBY app_file "test/#{path}/#{name}_test.rb", <<-RUBY
require 'test_helper' require 'test_helper'
......
...@@ -358,10 +358,12 @@ def remove_from_file(file, str) ...@@ -358,10 +358,12 @@ def remove_from_file(file, str)
end end
def app_file(path, contents, mode = "w") def app_file(path, contents, mode = "w")
FileUtils.mkdir_p File.dirname("#{app_path}/#{path}") file_name = "#{app_path}/#{path}"
File.open("#{app_path}/#{path}", mode) do |f| FileUtils.mkdir_p File.dirname(file_name)
File.open(file_name, mode) do |f|
f.puts contents f.puts contents
end end
file_name
end end
def remove_file(path) def remove_file(path)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册