pat / combustion

Simple, elegant testing for Rails Engines
MIT License
708 stars 51 forks source link

Application has been already initialized issue #84

Closed anson2590 closed 6 years ago

anson2590 commented 6 years ago

I am using rails 5 and ruby 2.4, when I try to run rspec for my gem works locally, I am getting runtime error in jenkins as follows below I have mentioned error and rails_helper code.

LoadError:
  cannot load such file -- rspec/rails
# /usr/local/bundle/gems/activesupport-5.1.5/lib/active_support/demo.rb:292:in `require'
# /usr/local/bundle/gems/activesupport-5.1.5/lib/active_support/demo.rb:292:in `block in require'
# /usr/local/bundle/gems/activesupport-5.1.5/lib/active_support/demo.rb:258:in `load_dependency'
# /usr/local/bundle/gems/activesupport-5.1.5/lib/active_support/demo.rb:292:in `require'
# ./spec/rails_helper.rb:14:in `<top (required)>'
# ./spec/controllers/sample/demo_controller_spec.rb:4:in `require'
# ./spec/controllers/sample/demo_controller_spec.rb:4:in `<top (required)>'

An error occurred while loading ./spec/models/demo_spec.rb.
Failure/Error: Combustion.initialize! :action_controller

rails_helper.rb file:

require 'spec_helper'

ENV['RAILS_ENV'] ||= 'test'
Dir[File.dirname(__FILE__) + '../internal/config/environment/*.rb'].each {|file| require file }

require 'combustion'
require 'support/shared_examples'

Combustion.initialize! :action_controller
Object.send(:remove_const, :ActiveRecord)

require 'rspec/rails'

RSpec.configure do |config|
  config.infer_base_class_for_anonymous_controllers = false
  config.include Rails.application.routes.url_helpers
  config.infer_spec_type_from_file_location!
end

Can anyone please help me to solve this issue.

pat commented 6 years ago

Can you share what's in your spec/rails_helper.rb and spec/spec_helper.rb? I think they might provide some helpful clues.

anson2590 commented 6 years ago

below is the rails_helper and spec_helper files with code.

rails_helper.rb require 'spec_helper'

ENV['RAILS_ENV'] ||= 'test'
# require File.expand_path("../../config/environment", __FILE__)
Dir[File.dirname(__FILE__) + '../internal/config/environment/*.rb'].each {|file| require file }

require 'combustion'
require 'support/shared_examples'

Combustion.initialize! :action_controller
Object.send(:remove_const, :ActiveRecord)

require 'rspec/rails'

RSpec.configure do |config|
  config.infer_base_class_for_anonymous_controllers = false
  config.include Rails.application.routes.url_helpers
  config.infer_spec_type_from_file_location!
end

spec_helper.rb require 'simplecov'

SimpleCov.start 'rails' do
  # Added this filter to exclude thrift files while calculating coverage report
  add_filter '/lib/'
end

RSpec.configure do |config|
  config.expect_with :rspec do |c|
    # disable the `should` syntax...
    c.syntax = :expect
  end
end
pat commented 6 years ago

Oh, I missed the fact that this only happens in Jenkins… that makes it more odd!

Has it ever worked for you in Jenkins? Are there any differences in how your tests are invoked on Jenkins compared to your own machine?

anson2590 commented 6 years ago

It has never build on jenkins. The order of execution in jenkins is first bundle will happen then specs will be executed.

pat commented 6 years ago

I don't suppose the Jenkins server and/or your gem code are publicly online anywhere? I'm really not sure what could be causing this problem.

anson2590 commented 6 years ago

Thanks for the help, it got worked the issue was add_development_dependency does not work with test environment, so added all dependency gems to group development and test, it fixed the issue.

pat commented 6 years ago

Great to know you found the solution :)

jrochkind commented 5 years ago

I ran into this odd error too. It has happened to me in a really odd way.

I have some tests that pass fine. My project uses both combustion and appraisal.

In my app, I have gem "chromedriver-helper" in my Gemfile. I saw that chromedriver-helper was EOL. Experimentally, I wanted to see what would happen if I simply removed it from my Gemfile.

Removing it from my gemfile, run bundle install just to be safe, and then trying to run bundle exec rspec -- I get this weird error.

I can't figure out how it would be related, or what to do about it. But have confirmed that if I add it back into Gemfile, everything is good; if I remove it, get this error. No other changes.

RuntimeError:
  Application has been already initialized.
# /Users/jrochkind/.gem/ruby/2.5.3/gems/railties-5.2.2.1/lib/rails/application.rb:360:in `initialize!'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/railties-5.2.2.1/lib/rails/railtie.rb:190:in `public_send'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/railties-5.2.2.1/lib/rails/railtie.rb:190:in `method_missing'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/combustion-0.9.1/lib/combustion.rb:32:in `initialize!'
# ./spec/spec_helper.rb:24:in `<top (required)>'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:291:in `require'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:291:in `block in require'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:257:in `load_dependency'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:291:in `require'
# ./spec/type/polymorphic_type_spec.rb:1:in `<top (required)>'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:285:in `load'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:285:in `block in load'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:257:in `load_dependency'
# /Users/jrochkind/.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/dependencies.rb:285:in `load'

My spec_helper.rb:24 is just: Combustion.initialize! :all

What? I'm at a loss here.

pat commented 5 years ago

Hrm. is it possible to alter your local copy of combustion to check whether Combustion.initialize! is being called just the once? Also, is it possible to share the full spec_helper.rb?

And of course, if the source code for this is available publicly, I'm happy to debug directly too :)

jrochkind commented 5 years ago

It is open source! https://github.com/jrochkind/attr_json/blob/master/spec/spec_helper.rb

While you can see that the Combustion.initialize has a block there, I removed the block, it didn't change the reproduction.

I don't expect or deserve it, but if you wanted to take a look at my source directly that would be very kind of you!

If you checkout master, and run ./bin/rspec, it should pass. If you remove the line gem "chromedriver-helper" from the Gemfile --it fails with this error. (For me? Maybe not for someone else?) (Yes, there are development dependencies in Gemfile not gemspec, I forget why but I think I had a reason)

While appraisal is being used in the project -- if you just run ./bin/rspec I don't think appraisal is actually involved at all in that run, so I don't think appraisal is involved in the error.

My best guess is that removing chromedriver-helper from the gemfile somehow would be causing a problem even if combustion wasn't involved at all, but for some reason combustion being involved makes the problem exhibit as the weird "application has already been initialized" problem. Which doesn't make a lot of sense, but it's the only hypothesis I got! Especially with this already filed issue -- perhaps somehow combustion can hide a true Rails boot error and turn it into this error instead.

It's also possible the problem won't reproduce for you at all -- it actually passed on travis even when I removed the line from the Gemfile. (Apparently it didn't need chromedriver-helper for anything, at least on travis!). So it may be somehow related to my local... state... somehow. I am not sure.

For me, if I or you don't figure it out relatively easily, I'll probably just not remove chromedriver-helper from my Gemfile for now, since I don't really need to.

jrochkind commented 5 years ago

Writing this out made me think, gee, maybe try deleting spec/internal/tmp/cache -- but that didn't seem to help.

Then I noticed, aha, I have a require 'chromedriver/helper' in my spec_helper.rb, that probably shouldn't be there if I don't have chromedriver-helper dependency anymore. But removing that... also didn't resolve issue, still reproduces.

This is all very odd indeed.

OK, I did put a debugger on Combustion.initialize! to see if it was being called twice -- indeed it was being called twice!

So okay, I'm thinking there is some problem in my app that prevents Rails boot... and that somehow leads to the spec_helper being executed twice? I can't quite figure out what would make that happen either.

Aha, and now paying more attention to my console output, I do see the original error! cannot load such file -- selenium/webdriver. OK, so indeed my testing setup is not ok, in the absence of the chrome-webdriver gem. The only odd thing is that it results in the double-load of spec_helper and the "Application has been already initialized" error. I'm thinking in the presence of combustion, you end up seeing this error when really something else is raising during spec_helper.rb/rails_helper.rb load time, or rails app boot in general.

jrochkind commented 5 years ago

OK, and that's because I had accidentally removed gem "selenium-webdriver" from my Gemfile too.

When I put that back in (thanks git for making sure I can always see exactly what I've changed), I no longer get "application has already been initialized". I get failures, but they are not combustion related, they are clearly related to my removal of chromedriver-helper -- "Selenium::WebDriver::Error::WebDriverError: Unable to find chromedriver.". Great, that's what I actually expected!

So the issue may actually be -- if you have a "require" in your spec_helper.rb that fails... somehow this results in the spec_helper.rb being called multiple times (?), and a "Application has been already initialized" error from combustion. The original error is probably still there in your console, but you may miss it cause your console is full of multiple subsequent "Application has been already initialized issue". Weird.

pat commented 5 years ago

Glad you've found a way through this!

I wonder, do you have --require spec_helper in your .rspec files (either at a project or user level)? I'm wondering if the first require is from that, but it fails non-obviously, and then the spec file itself loads the spec_helper too, and you get the second duplicate app initialisation? 🤔