Fitter Man
Fitter Man

Reputation: 682

Rails 4, New App: Why do tests run in development environment?

I have simple, new Rails 4 app which clobbers the development database when I run rake test:units, even though I've set the RAILS_ENV in test_helper.rb. I wouldn't have expected that. Here are the simple steps to reproduce it.

I have Ruby 2.0.0p247 and Rails 4.0.1.

rails new foo
rails generate scaffold gadget
rake db:migrate

I edit test/models/gadget_test.rb to look like this:

require 'test_helper'

class GadgetTest < ActiveSupport::TestCase
  test "the env" do
    assert_equal "test", Rails.env
  end
end

and I have edited the first line of test/test_helper.rb from

ENV["RAILS_ENV"] ||= "test"

to be

ENV["RAILS_ENV"] = "test"

Even so, when the tests invoke rake test:units it fails:

  1) Failure:
GadgetTest#test_the_env test/models/gadget_test.rb:5]:
Expected: "test"
  Actual: "development"

With older (Rails 3) apps I've set up, I could count on this defaulting to the test environment. What am I missing?

Upvotes: 5

Views: 2960

Answers (4)

JonathanSimmons
JonathanSimmons

Reputation: 1558

As far as I can tell there shouldn't be any reason to have to force the Rails.env to the test. So if you're test are running in the wrong env there is something setting the env somewhere in your code.

For me it was caused by env export I didn't realize someone had placed on the first line of an .rvmc file for the app.

Removing that export RAILS_ENV=development line from that file and restarting terminal fixed the issue.

Upvotes: 0

Fitter Man
Fitter Man

Reputation: 682

The real answer: there was a stray export RAILS_ENV="development" in a shell script referenced by my profile. So this is a seat-to-keyboard interface failure, directly from Oct 31, 2013 in this thread: https://github.com/rails/rails/issues/7175

All you need to do is take that out and the problem goes away.

Upvotes: 1

Anton Dieterle
Anton Dieterle

Reputation: 656

TL;DR ensure that require 'rails/test_unit/railtie' line is not commented out in config/application.rb


I had the same problem, was trying out Minitest as a replacement for TestUnit, and generated Rails application without it (rails new foobar --skip-test-unit), but Minitest still uses test task from rails.

And I had the following code in the config/applicaiton.rb:

# require 'rails/test_unit/railtie'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

As j_mcnally and Fitter Man pointed out, the problem is that Rails.env caches its value before ENV['RAILS_ENV'] got set, in my case it is getting called inside Rails.groups.

Trying to find in Rails sources how it sets proper test env when calling rake task, I found that it does so in the rails/test_unit/railtie.rb which got commented out.

So the solution was as simple as uncommenting require 'rails/test_unit/railtie' line.

Hope that helps.

Upvotes: 6

Fitter Man
Fitter Man

Reputation: 682

Mystery solved, with a big tip of the hat to j_mcnally!

To force the Rails env to "test" in Rails 4 (and probably much earlier), it no longer suffices to change the first line of the test_helper.rb to

ENV["RAILS_ENV"] = "test"

This fails to reset the cached value of Rails.env, but if you invoke

Rails.env = "test"

It will reset the cached value properly. That said, there are other places where Rails.env is being invoked already, otherwise the cache wouldn't be set. One obvious one is bundler setup in application.rb, where it has Bundler.require(:default, Rails.env) and changing that to Bundler.require(:default, ENV['RAILS_ENV']) (to avoid setting the cache) still indicates that other places in the initialization must also be invoking Rails.env. The significance of all of that is that some of the setup is going to think it's running in development and then the tests will run in the "test" environment.

Net answer: I have a way to get what I want, but there may still be some danger spots lurking out there.

Upvotes: 6

Related Questions