2

I'm just working on my first rails application by following the tutorial at http://ruby.railstutorial.org/. I have setup my development environment exactly as what it says in the tutorial (I'm on using a Macbook Pro with Lion) and it's working without any issues except for just one hiccup. I write failing tests first then I make changes to the code so that they pass, I can check in the browser that the pages are working correctly but for some reason, the test results are still "Red". I have a terminal running with 3 tabs, first tab where I have spork running (bundle exec spork), second tab where I have rails server running (rails s) and third tab where I make all the command line changes and run tests (autotest || bundle exec rspec spec/). I have to restart spork, rails server and then test again to see them go "Green".

Is this an expected behaviour? Because as per the tutorials most of the times I should be able to see them go green without having to restart the server/spork.

EDIT

This is what my spec_helper.rb file looks like

require 'rubygems'
require 'spork'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.

  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'


  # Requires supporting files with custom matchers and macros, etc,
  # in ./support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    # == Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr
    config.mock_with :rspec

    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, comment the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true
  end

end

Spork.each_run do
  # This code will be run each time you run your specs.
end

Thanks for advising!

Hiral Desai
  • 1,062
  • 1
  • 9
  • 24

6 Answers6

17

I've just run into the same issue when trying to set up an environment with spork and watchr, and found the solution (at least in my case) here: http://www.rubyinside.com/how-to-rails-3-and-rspec-2-4336.html

Edit config/environments/test.rb

Change

config.cache_classes = true

to

config.cache_classes = false

This should get spork to pick up changes to your controllers and models without a restart.

Edit:

I've since run into problems with cache_classes set to false (it was causing problems with machinist and cucumber - rspec and machinist was fine oddly enough).

Anyway, it seems there is a better solution (taken from here: http://ablogaboutcode.com/2011/05/18/spork-rspec-sham-and-caching-classes/ and here: http://mikbe.tk/2011/02/10/blazingly-fast-tests/) that is to add the following code to your Spork.each_run block

Spork.each_run do
  ActiveSupport::Dependencies.clear
  ActiveRecord::Base.instantiate_observers

  load "#{Rails.root}/config/routes.rb"
  Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }  
end if Spork.using_spork?
Sam Peacey
  • 5,964
  • 1
  • 25
  • 27
1

If your using spork rc 1.0 you need to use 'spork-rails' instead.

Fixed the problems of controllers not reloading for me. Thanks to this post.

http://blog.firsthand.ca/2012/02/heads-up-use-spork-rails-if-you-want-to.html

Phil Dudley
  • 326
  • 3
  • 4
1

Does it work if you run your test without changes? I mean does it 'pick up' your changes?

If that's the case, open spec_helper.rb and change each_run block so it loads your tests requirements you need each time, not just only once, as it loads.

socjopata
  • 5,028
  • 3
  • 30
  • 33
  • It picks up the new tests, it doesn't pick up the changes to the code to make the tests pass. I have modified my Question to show you the structure of spec_helper.rb file. – Hiral Desai Aug 30 '11 at 10:34
  • Would you be able to tell me what should I put in each_run to make sure all changes get picked up before each test run? My changes consist of "changes to routes.rb, changes to controller method, changes to partials and views). – Hiral Desai Aug 30 '11 at 10:43
0

Adding to Sam Peacey's answer, in newer versions of Rails instantiate_observers has been deprecated, and removing that one line still produces the desired result:

Spork.each_run do
  ActiveSupport::Dependencies.clear

  load "#{Rails.root}/config/routes.rb"
  Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }  
end if Spork.using_spork?
0

I'm going through the same tutorial and ran into the same problem. Here's what ended up working for me:

  1. Update the 'spec/spec_helper.rb' file to change change the 'Spork.prefork' section to:

    Spork.prefork do
    
      # Loading more in this block will cause your tests to run faster. However,
      # if you change any configuration or code from libraries loaded here, you'll 
      # need to restart spork for it take effect.
    
      ENV["RAILS_ENV"] ||= 'test'
      require File.expand_path("../../config/environment", __FILE__)
      require 'rspec/rails'
    
      # Requires supporting files with custom matchers and macros, etc, 
      # in ./support/ and its subdirectories. Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
    
      RSpec.configure do |config|
    
      # == Mock Framework
      #
      # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: #
      # config.mock_with :mocha
      # config.mock_with :flexmock 
      # config.mock_with :rr config.mock_with :rspec
          config.fixture_path = "#{::Rails.root}/spec/fixtures"
    
      # If you're not using ActiveRecord, or you'd prefer not to run each of your 
      # examples within a transaction, comment the following line or assign false 
      # instead of true.
    
      config.use_transactional_fixtures = true
      end  
    
    end
    
  2. Update the 'config/environments/test.rb' file to change:

    config.cache_classes = true
    

    To:

    config.cache_classes = false
    

It's that second point that isn't mentioned in the book. I figured it out by cross referencing other StackOverflow questions. In my case, before turning off 'config.cache_classes', any changes I would make to the controller would case the test suite to run, but it won't take the edits into account. This would cause false positives and false negatives depending on the last test run. After disabling the setting, the tests pick up my edits and provide valid pass/fail indicators as far as I can tell.


Note that if a views (.erb) file passed a test once, it doesn't seem to get picked up again if you change it. However, if the view fails, spork seems to keep watching it for changes until it passes.

Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
-2

in env.rb (the file you set up the spork) you have two blocks prefork and each_run. Here you have explanation what they do:

Spork.prefork do
      # Loading more in this block will cause your tests to run faster. However, 
      # if you change any configuration or code from libraries loaded here, you'll
      # need to restart spork for it take effect.
end

and

Spork.each_run do
    # This code will be run each time you run your specs.
end

I think it is self-descriptive ;)

Ireneusz Skrobis
  • 1,533
  • 1
  • 11
  • 12
  • Would you be able to tell me what should I put in each_run to make sure all changes get picked up before each test run? – Hiral Desai Aug 30 '11 at 10:43
  • Probably everything from prefork ;) But you shouldn't do this. Spork is used to make your tests load faster. So you should put as many things as possible to prefork. I know that reloading Spork when you change something in your code is a small inconvenience but... usually, you will be writing tests after you finish some work and test it manually. So changes in code will be not required. In this situation you will be really happy that tests start faster after each of your changes (in this tests). – Ireneusz Skrobis Aug 30 '11 at 11:25
  • Okay, so basically what I should be doing is restarting the spork every time I make a set of changes instead of expecting it to pick it up automatically? – Hiral Desai Aug 30 '11 at 12:01
  • Yes - if you change something in models/controllers. If you change something in the views then it should works without restart. – Ireneusz Skrobis Aug 30 '11 at 12:08
  • Your "solution" assumes (even promotes) a non-TDD workflow and doesn't solve the problem stated by the OP. Hence: downvote. – steve Oct 18 '12 at 08:46
  • Yes, you have right steve. Today I know that this is a wrong answer, but a year ago I was sure it was a correct one... It's a mistake and it should be deleted. – Ireneusz Skrobis Oct 19 '12 at 05:39
  • @Hiral. Unfortunately, when I click "delete" then I get: "You cannot delete this accepted answer". Can you please remove acceptance for this one? – Ireneusz Skrobis Oct 19 '12 at 05:48
  • Sorry, I saw this very late. Removed acceptance now. BTW - this was a correct answer when I answered it. :-) – Hiral Desai Apr 08 '19 at 21:41