Spork is not speeding up my tests - ruby-on-rails

I'm using RSpec for my Rails 3 tests and trying to use Spork.
I followed several tutorials and Spork seems to be running with no errors, but my tests still take the same amount of time to run (43 seconds) with Spork on and off.
How can I figure out what's going on?
Gemfile
gem 'spork', '>=0.9.0.rc9'
spec_helper.rb
require 'rubygems'
require 'spork'
require 'factory_girl'
require 'cover_me'
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.
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
# Force find of factory girl definitions. Tests started failing without this, and the factories could not be found
Factory.find_definitions
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/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
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
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, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# Needed for Spork
ActiveSupport::Dependencies.clear
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end
When I run →spork to start the server everything looks fine:
→ spork
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
I also have --drb in the .rspec file

It depends on how you measure execution time. If you are including the time it takes to spin up rails that should be faster, but actual test run time wont change.
Spork caches the rails environment which speeds up spin up time but it doesn't speed up actual execution time.

Related

Rspec loading old schema

I am working on a legacy project (recently upgraded from rails 4.1 to 5.2) and I had to change an association table. Before:
reports had many clients and clients had many reports. Now I have created a ClientsReport table than not only holds the client_id and reports_id but also has an id as primary_key and a can_manage (boolean).
Testing with rspec it is giving me an error when calling reports_clients.for(report).first.can_manage
saying unKnownAttribute can_manage for <ClientsReport client_id: 1, report_id:3> no sign if id nor can_manage
So it looks like it is using the old schema.
Also tried adding ActiveRecord::Migration.maintain_test_schema! as suggested here but I am not sure
I tried running rake:db:prepare but it threw me a bunch of errors and now looks like I broke the test db, as I was having 4 failing tests and now I have 166...
My spec_helper.rb looks like this:
Spork.prefork do
require 'simplecov'
SimpleCov.start 'rails'
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'devise'
require './spec/controllers/controller_helpers.rb'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, type: :controller
config.include ControllerHelpers, type: :controller
config.include Capybara::DSL
# ## 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
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
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, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
config.infer_spec_type_from_file_location!
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
config.include FactoryGirl::Syntax::Methods
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end
You can completely reset the test DB with this command, after making sure your schema is up to date.
bin/rails db:environment:set db:drop db:create db:schema:load RAILS_ENV=test

Can't get rspec working with Zeus

I've read all the recommendations about how to get rspec on rails working with zeus. In particular, I've commented out "require 'rspec/autorun'" in spec/spec_helper.rb:
# require 'rspec/autorun'
I start up zeus in one terminal:
zeus start
Then in another terminal run rspec:
zeus rspec spec/controllers/source_configs_controller_spec.rb
And get... nothing. No output, no response, nada - just dumps me back to command line. However, if I uncomment require 'rspec/autorun' in spec_helper.rb, and run it again, I get:
Failure/Error: post :create, {:account_id => #account.id, :source_config => valid_attributes.except(:account_id)}, {}
NoMethodError:
undefined method `post' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1::Nested_1:0x007fbdff3032d8>
Any ideas? I feel like I've lost more time trying to figure this out than I'll ever recover with speedier rspec runs... so frustrating.
After more digging and experimentation, it looks like rr (mocking framework) in spec_helper.rb was the culprit. I had
RSpec.configure do |config|
config.mock_with :rr
#...
end
To fix it:
Upgrade rr ("bundle update rr").
Initialize rr in a different manner:
In Gemfile
group :development, :test do
gem "rr", :require => false # important to specify ":require => false"
gem "rspec-rails"
# (any other appropriate gems)
end
In spec_helper.rb
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
# vvvv NOTE: this is how you enable rr now
require 'rr'
#require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/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
# vvvv NOTE: Make sure this line is commented out
# config.mock_with :rr
# ... other rspec config
end
Would love to hear anyone else's thoughts - is there a better way?
So I was having the same issue and using some debugging I found that the tests were being run, but there was no output.
What worked so far is putting config.reset at the top of the RSpec.configure block. I got that idea from here: https://github.com/burke/zeus/issues/461 which got the idea from here: How can I configure rspec to show output with spork?
As a warning, one of the comments in the first link mentions that putting config.reset has undesirable side effects, but I have not run into any .... yet.

Rspec not loading model

Here is my code:
require "user"
require "spec_helper"
describe User do
end
and spec_helper.rb file
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
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
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
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, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
user_sprec.rb is located the same folder with spec_helper.rb both inser
#{Rails.root}/spec folder
error message I got when i ran "rspec user_spec.rb"
usr/local/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require': cannot load such file -- user (LoadError)
from /usr/local/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
from /home/li/data/git/mgm/spec/user_spec.rb:1:in `<top (required)>'
RSpec is designed to be run from the project's root directory. I suspect you are running it from within the spec directory, which results in the error you are seeing. Try again from the root directory, passing spec/user_spec.rb. Also, the require user is superfluous within your spec, since user.rb will be autoloaded as a result of your reference to the User constant.

Spork doesn't reload code

I am using following gems and ruby-1.9.3-p194:
rails 3.2.3
rspec-rails 2.9.0
spork 1.0.0rc2
guard-spork 0.6.1
Full list of used gems is available in this Gemfile.lock or Gemfile.
And I am using this configuration files:
Guardfile
.rspec
spec_helper.rb
factories.rb
If I modify any model (or custom validator in app/validators etc) reloading code doesnt works.
I mean when I run specs (hit Enter on guard console) Spork contain "old code" and I got obsolete error messages. But when I manually restart Guard and Spork (CTRC-C CTRL-d guard) everything works fine. But it is getting tired after few times.
Questions:
Can somebody look at my config files please and fix error which block updating code.
Or maybe this is an issue of newest Rails version?
PS This problem repeats and repeats over some projects (and on some NOT). But I haven't figured out yet why this is happens.
PS2 Perhaps this problem is something to do with ActiveAdmin? When I change file in app/admin code is reloaded.
Workaround:
# config/environments/test.rb
config.cache_classes = false
But it is "double-edged sword".
Specs run now ~2.0x time longer. But it is still faster than restarting again and again Spork.
Update 28.06.2013
Use Zeus. It works perfectly. Benchmarks are at the bottom..
If you are using 1.9.3 consider installing special patches which REALLY speed up loading app.
RVM patchsets
rbenv instructions
Background & Benchmark:
I have a quite large 1.9.3 app and I wanted to speedup app loading, Spork doesn't work so I started looking for other solutions:
I write a empty spec to see how long it takes to load my app
-/spec/empty_spec.rb
require 'spec_helper'
describe 'Empty' do
end
plain 1.9.3
time rspec spec/empty_spec.rb 64,65s user 2,16s system 98% cpu 1:07,55 total
1.9.3 + rvm patchsets
time rspec spec/empty_spec.rb 17,34s user 2,58s system 99% cpu 20,047 total
1.9.3 + rvm patchsets + zeus
time zeus test spec/empty_spec.rb 0,57s user 0,02s system 58% cpu 1,010 total
[w00t w00t!]
Alternatively, you can add guards for your models, controllers and other code. It'll make guard reload spork when any of these files change.
guard 'spork',
:rspec_env => {'RAILS_ENV' => 'test'} do
watch(%r{^app/models/(.+)\.rb$})
watch(%r{^lib/(.+)\.rb$})
end
I had the same problem. Tests were reloaded and ran successfully for changes to model_spec.rb. When I made changes to the model.rb file the tests were re-run, however the code seemed to be cached - so the changed were not applied.
It required a combination of a few answers to get things working:
# /config/environments/test.rb
config.cache_classes = !(ENV['DRB'] == 'true')
# spec_helper.rb
Spork.each_run do
.....
ActiveSupport::Dependencies.clear
end
I also updated spork to (1.0.0rc3) and replaced the spork gem with spork-rails, as mentioned by #23inhouse above. However, I did not see any difference between either gem in the gemfile although upgrading spork may have had an effect.
Hopefully this helps someone else not spend any more hours banging their head against the wall.
Great as Spork is, it seems to break on every Rails upgrade :(
On Rails, 3.2.3, I've added this snippet in spec/spec_helper.rb to forcibly reload all ruby files in the app directory.
Spork.each_run do
# This code will be run each time you run your specs.
Dir[Rails.root + "app/**/*.rb"].each do |file|
load file
end
end
In my case the problem was draper. It didn't allow spork to reload the models.
Spork.prefork do
ENV['RAILS_ENV'] ||= 'test'
# Routes and app/ classes reload
require 'rails/application'
Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
Spork.trap_method(Rails::Application, :eager_load!)
# Draper preload of models
require 'draper'
Spork.trap_class_method(Draper::System, :load_app_local_decorators)
# Load railties
require File.expand_path('../../config/environment', __FILE__)
Rails.application.railties.all { |r| r.eager_load! }
...
Just remember to insert the trap method for Draper before loading the environment.
Spork got cleaned up and some functionality was extraced.
https://github.com/sporkrb/spork-rails
add this to your Gemfile
gem 'spork-rails'
Fixed the same problem by adding more to the spork.each_run method.
Rails 3.2.2
Also, I recommend running one test a time. It's much faster, less noisy, and we normally work on one test at a time anyway.
rspec spec -e 'shows answer text'
I find it is faster and easier than using Guard because I was just sitting around waiting for Guard to finish. Also, Guard did not always reload the right files and run the right tests when I made a change.
spec_helper.rb file:
require 'spork'
Spork.prefork do
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
require 'capybara/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
end
Spork.each_run do
Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f}
RSpec.configure do |config|
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
config.mock_with :rspec
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
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, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
config.include RequestHelpers, :type => :request
config.before :suite do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with :truncation
end
config.before :each do
DatabaseCleaner.start
end
config.after :each do
DatabaseCleaner.clean
end
config.include(MailerHelpers)
config.before(:each) { reset_email }
end
# This code will be run each time you run your specs.
end

RSpec+Capybara request specs w/ JS not working

I cannot get request specs working when using Javascript.
My specs pass if I run them without Javascript (the page is built to work with or without JS).
Specifically, the specs fail when I do assertions like Post.should have(1).record.
Capybara just doesn't pick up the records from the DB, and the database is not cleaned between runs.
I've tried using DatabaseCleaner with transactional fixtures disabled - the common approach to this, I guess. No dice.
I've also tried (and, would ideally prefer) running without DatabaseCleaner, using transactional fixtures and forcing AR to share the same connection between threads (a patch described by José Valim). Again, no dice.
Additionally, I've also tried switching between Capybara-webkit and Selenium - the issue persists.
I've put up a sample app with just a basic Post scaffold, that replicates the problem: https://github.com/cabgfx/js-specs
There's a spec_helper.rb with transactional fixtures and AR shared connection, and a spec_helper_database_cleaner.rb for the other scenario.
I normally use Spork, but I've disabled it in both spec_helper.rb files, just to eliminate a potential point of failure (in both apps; the "real" one and the sample app).
I develop locally using Pow on a Macbook Air, running OS X 10.7.3 with MRI 1.9.3 thru RVM. (I also tried on 1.9.2).
Hope I'm making sense - any guidance/help/pointers are greatly appreciated!
Matt - thanks a lot for taking time to assist me!
I tried setting it up with your spec_helper, using Selenium as the javascript driver.
The spec still failed - but I could see the correct behavior being executed in Firefox...
Then it dawned on me, that the problem might occur because of Capybara not waiting for AJAX requests to finish.
I then reverted to my initial spec_helper (with Spork and no DatabaseCleaner), and simply used Capybara's wait_until { page.has_content? "text I'm inserting with JS" }.
I updated the sample app, and just added sleep 1 in the request spec, so you can see for yourself. It now works with and without Spork, and the AR monkey patch seems to work perfectly.
I have tried your code with the spec_helper.rb listed below and the test passes. Note that the syntax for triggering database cleaner is a bit different than in your spec_helper_database_cleaner.rb.
We're using this in production, and we've also tried the modification suggested by Jose Valim but it didn't work for us - this did.
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'
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.
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Add this to load Capybara integration:
require 'capybara/rspec'
require 'capybara/rails'
include Capybara::DSL
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/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
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
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, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Include sign_in & sign_out for tests
# config.include Devise::TestHelpers, :type => :controller
# Use database_cleaner to ensure a known good test db state as we can't use
# transactional fixures due to selenium testing
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end
José's suggestion worked for me but not when I used Spork. But adding this to spec_helper.rb did:
Spork.prefork do
RSpec.configure do |config|
# Make it so poltergeist (out of thread) tests can work with transactional fixtures
# http://www.opinionatedprogrammer.com/2011/02/capybara-and-selenium-with-rspec-and-rails-3/#post-441060846
ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do
def current_connection_id
Thread.main.object_id
end
end
end
end
Source: http://www.opinionatedprogrammer.com/2011/02/capybara-and-selenium-with-rspec-and-rails-3/#post-441060846

Resources