Rails Project Using Spork - Always Have to Use Spork

Rails project using spork - always have to use spork?

No. We have spork in our spec helper and we don't use it a lot of the time, since it slows the tests down overall on larger suites. We only run spork when we're rapidly iterating, running a small subset of the tests repeatedly during TDD. When spork is not running, we simply do not pass the --drb option to RSpec and everything runs without Spork. Obvious Spork is there, but it doesn't get used unless we start it and run our specs with --drb.

If you don't want the prefork blocks and stuff there, require an environment variable to be set before you execute them, so you can conditionally by-pass them, if they are causing an issue for you.

EDIT | I've just split our spec helper into multiple files so the prefork block isn't loaded at all when we're not running Spork. It's not needed, but here's how I did it.

spec_helper.rb loads one of two different files after doing a quick environment check)

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

# Conditional Spork.prefork (this comment is needed to fool Spork's `bootstrapped?` check)
if /spork/i =~ $0 || RSpec.configuration.drb?
require File.expand_path("../spec_helper_spork", __FILE__)
else
require File.expand_path("../spec_helper_base", __FILE__)
end

spec_helper_base.rb is just a copy of the original spec_helper without Spork (you can just rename it back if you delete Spork)

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

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'database_cleaner'

# Load all .rb helper files under the support/ directory
Dir[Rails.root.join("spec/support/**/*.rb")].each { |file| require file }

RSpec.configure do |config|
# ... the usual stuff ...
end

And finally spec_helper_spork.rb is just a wrapper around spec_helper_base.rb

require 'spork'

Spork.prefork do
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'database_cleaner'
end

Spork.each_run do
$rspec_start_time = Time.now
require File.expand_path("../spec_helper_base", __FILE__)
end

The only time spec_helper_spork.rb is loaded is if you:

a) Invoke the spork command
b) Run your specs with the --drb option

This is working fine for me. I can't stress enough though, that it's not needed. Your specs will run fine without spork running provided you don't pass the --drb option anyway. I do like having it completely split out of our spec helper now that I've done this though.

How to use Rails.vim and spork?

Turns out that Rails.vim will use Spork if you add the --drb option to your spec.opts file automatically.

Spork.prefork is loading app/models/*

After much time spinning my wheels I finally have something that is acceptable:

Spork.prefork do
require "rails/mongoid"
Spork.trap_class_method(Rails::Mongoid, :load_models)

# The following does not work correctly with Devise's routes that load the User model.
# Results in NameError unintitialized *
# :reload_routes! triggers :devise_for which loads and caches the User class.
# https://github.com/timcharper/spork/wiki/Spork.trap_method-Jujutsu
# require "rails/application"
# Spork.trap_method(Rails::Application, :reload_routes!)

require 'factory_girl_rails'
Spork.trap_class_method(Factory, :find_definitions)

require File.expand_path(File.dirname(__FILE__) + '/../config/environment')

end

The problem was mostly due to Rails::Mongoid#load_models. After inspecting the debug output of spork and the backtrace of how things are loaded, some clues are provided as to what is loading the models. This page goes into a bit more detail https://github.com/timcharper/spork/wiki/Spork.trap_method-Jujutsu, but I do not find the :reload_routes! helping with Devise forcing the User class to be preloaded.

My specs are running much faster now. If only I could get my User model to not be cached I would be in bliss, but until then, I shall be mostly satisfied.

How to transition from spork to spring?

As you mention in your question, there is no Prefork block. The docs provide a workaround: simply move your existing Spork.prefork block to an initializer or anywhere that it will be picked up and run at load time by Rails.

From https://github.com/rails/spring#running-code-before-forking:

There is no Spring.before_fork callback. To run something before the fork, you can place it in ~/.spring.rb or config/spring.rb or in any of the files which get run when your application initializes, such as config/application.rb, config/environments/*.rb or config/initializers/*.rb.

As for your Spork.each_run block, since you're using Rspec you could move it into a before(:suite) block. See the Rspec docs on before and after hooks

Guard + spork + Rspec issue - How do I remove hooks to Test::Unit?

Or you can add test_unit: false as an option to guard-spork, i.e. in your Guardfile:

guard 'spork', :rspec_env => { 'RAILS_ENV' => 'test' }, :test_unit => false do

I acutally have some performance tests in my 'test' directory, so removing test/ is not always an option.

Spork doesn't reload code

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!]

Running Spork for rails on linux using Virtual Box - Port in use error

When using a non-default port for the DRb server you can tell RSpec to use that alternate port by adding --drb-port [PORT] to your rspec call.

spork -p 5555
rspec spec --drb --drb-port 5555

Of course you can put all the rspec options into your .rspec file, then just remember to run that port when you fire up spork.



Related Topics



Leave a reply



Submit