Rails with Factory Girl Configuration possible Scoping Issue, best practices? - ruby-on-rails

In the Factory Girl getting started documentation it says to include the helper module like this:
# RSpec
# spec/support/factory_girl.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
Inside the RSpec config block. But this doesn't work for me. I just put module inclusion the beginning of the rails_helper.rb and it works fine.
My question is why does the documentation say to put it in the config block? Should that be working? Am I going to run into method collisions. Am I going against best practices?

Files residing in spec/support are not loaded by default. Uncomment line #21 in spec/rails_helper.rb for Rails 4.2.

Related

Rspec use application controller method

I have method in my application controller and want to use it everywhere
in my integration specs.
I don't want to add it method in every spec
Currently i use
allow_any_instance_of(ApplicationController).to receive(:set_seo).and_return('seo_text')
but it is inconvenient.
What should i do for it?
In your Rspec config you can configure a before and after block for :
before suite
before all
before each
after each
after all
after suite
https://www.relishapp.com/rspec/rspec-core/v/2-2/docs/hooks/before-and-after-hooks
In that order.
I would suggest:
RSpec.configure do |config|
config.before(:suite) do
allow_any_instance_of(ApplicationController).to receive(:set_seo).and_return('seo_text')
end
end
Edit:
It appears that before(:suite) can cause problems.
If it doesn't work for you use before(:each)
I would create a spec_helper_integration file and put functionality specific to integration specs in there.
You should already have require 'rails_helper' at the top of all your specs. At the top of your integration specs put:
require 'rails_helper'
require 'spec_helper_integration'
Then create a spec_helper_integration.rb file in the same folder as your rails_helper.rb file.
spec_helper_integration:
#I'm taking a guesstimate as to your integration spec configuration, but it's
#likely something like the following line:
#don't also have this in your spec_helper or rails_helper files:
require 'capybara/rails'
#configure your integration specs:
RSpec.configure do |config|
config.before(:each) do
allow_any_instance_of(ApplicationController).to receive(:set_seo).and_return('seo_text')
end
end
It's good practice to isolate code to where it is required only; by doing this, your ApplicationController method stubbing is only activated during the running of your integration specs and not your other specs, such as unit or controller specs, for example.
Moving forward, any further integration-spec-specific code should only be put in your spec_helper_integration file, too.

How to add "config.include FactoryBot::Syntax::Methods" to rspec config block in spec_helper.rb?

If I add:
config.include FactoryBot::Syntax::Methods
under
RSpec.configure do |config|
and run rspec, I see this error:
/Users/perry_mac/rails_projects/mymri/spec/spec_helper.rb:21:in `block
in ': uninitialized constant FactoryBot (NameError)
my gemfile.lock can be seen in this pastebin
my gemfile can be seen in this pastebin
If I omit the Rspec.configure statement, my tests all run fine. I'd like to make use of the abbreviated syntax, but am not sure what I am doing wrong here.
Note: FactoryBot was previously called FactoryGirl
Got it.
This link showed me the way.
The required addition should be made in spec/support/factory_bot.rb and it should look like this:
# RSpec
# spec/support/factory_bot.rb
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
Note: FactoryBot was previously called FactoryGirl
You must add this string in file 'spec/RAILS_helper.rb' not in 'spec_helper.rb'
Also make sure to require 'factory_bot' in spec/support/factory_bot.rb
That's what ended up being the issue for me.
Make sure to include require 'support/factory_girl' in spec/rails_helper.rb after require 'rspec/rails'.
I was getting this error after putting it right after require 'spec_helper'.
This answer is compiled and tested from previous comments and factory_bot.
Create spec/support/factory_bot.rb file.
Paste inside spec/support/factory_bot.rb file:
require 'factory_bot'
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
Add require 'support/factory_bot.rb' in spec/rails_helper.rb file.
Write tests with pleasure.
I think it's worth mentioning here that, going forward, if using FactoryGirl, you will receive a deprecation message:
The factory_girl gem has been deprecated and has been replaced by factory_bot. Please switch to factory_bot as soon as possible.
Just a note for developers in the future that are trying to use FactoryGirl.

How To Use Spree Route Helpers in RSpec

I am trying to use the Spree 2.3 route helpers in Rspec 3.0. In the main app, I can access them by prefixing spree., like so:
spree.admin_login_path => 'spree/admin/user_sessions#new'
However I can't seem to access them in Rspec.
#rspec error
undefined local variable or method `spree_admin_login_path'
I've found reference to including the helpers in the rails_helper file, but this throws an error
# app/spec/rails_helper.rb
RSpec.configure do |config|
config.include Spree::Core::UrlHelpers
end
# configuring the above results in the following
app/spec/rails_helper.rb:21:in `block in <top (required)>': uninitialized constant Spree (NameError)
How do I access the spree routes given in $ rake routes in my tests?
After digging through the Spree code I was able to put together this setup for my rails_helper file that lets me use spree routes such as spree.admin_login_path in my spec files:
# app/spec/rails_helper.rb
require 'spree/testing_support/url_helpers'
RSpec.configure do |config|
config.include Spree::TestingSupport::UrlHelpers
end
I'm sure there's a smoother way to include all of Spree's test helpers, and I'd love to hear about it from someone who knows.

View helper methods not included for Devise views in rspec integration/request tests?

When I visit my sign in page in a browser everything works fine.
When I visit my sign in page in an rspec integration/request test, I get the following error:
ActionView::Template::Error:
undefined method `title' for #<#<Class:0x00000007af9180>:0x00000007af32a8>
The title method is used by the view and defined in ApplicationHelper which devise seems to find when using the browser. However, during rspec integration tests, devise is unable to find the helper method.
Is there anything I should be stubbing? It seems wrong to be stubbing in integration tests. Any other ideas?
(This question is not about how to include devise helpers in integration tests. I'm manually filling in the sign in forms to authenticate).
Looks like this issue. (in some cases related to ActiveAdmin https://github.com/gregbell/active_admin/wiki/Use-spork)
Here I found a hack that works for me (REE 1.8.7, Rails 3.1, Capybara, Devise, active_admin).
However, this is not likely to be merged, so I forked spork-rails to here with that patch applied. And as you probably know I can point my Gemfile to that repo:
gem 'spork-rails', :git => "git://github.com/chopmo/spork-rails.git"
Not optimal but it gets the job done for now.
I had a similar problem using Cucumber when I installed devise:
undefined local variable or method `flash_block' for #<#<Class:0x007ffd0a28dae8>:0x007ffd0b2f6d58> (ActionView::Template::Error)
I solved it by including the module in env.rb
Spork.prefork do
include FlashBlockHelper
I hope this helps.
Inside /spec/support create devise.rb with this:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
Make sure your spec_helper.rb includes:
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
and that your specs have:
require 'spec_helper'

Spork: how to refresh validations and other code?

I've been using spork all day, and most of the time it is a really great.
However, I am often running into a few problems where I need to restart Spork in order for my tests to pass... and now I'm wondering if it's more trouble than it's worth. I am new at ruby, so sometimes I can't predict if the error is due to a refresh problem, or if the error is due to my unfamiliarity with Ruby and Rails.
What do I need to put into Spork.each_run block so that my validations and other things are refreshed so that I don't have to restart the spork server?
Thanks
EDIT: If you can upgrade to Ruby 2.0 this is your best bet. It is fast enough and will let you work in regular way without the need for tools like Spork, Zeus, and ect. And in essence you won't need anything I wrote below.
If you still need some speed bump while developing check out the Fast Rails Commands cast.
Well yes, you want to reload Spork if you changed environment, initializer or spec_helper files (and for that guard-spork is perfect), but not when you updated one of your classes (models) as this would deny the purpose of tools like spork. I had the very same issue: I could delete all methods in a model, and tests would still pass, because Spork hold "old" model class in memory. Restarting Spork was required.
Reason:
Some plugins cause the model code to be preloaded so some work is required to block that from happening.
https://github.com/sporkrb/spork/issues/37
https://github.com/sporkrb/spork/issues/94
You want to prevent model code preloaded, as this will not "reload" them if you make any changes (like with validations).
Solutions:
Depends from gems that are involved. In my case, I had to deal with Devise and FactoryGirl, but in essence, you do it by using Spork.trap_method as described on wiki: https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujitsu
Additionally you can run spork -d to get a list of files that are preloaded, it may be helpful to track which gems may be involved in causing this issue.
Example:
Rails 3.0.x + Rspec2 + Spork 0.9.0.rcX + Capybara + Devise + FactoryGirl
# spec/spec_helper.rb
Spork.prefork do
# 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 'capybara/rspec'
require 'capybara/rails'
# set "gem 'factory_girl', :require => false" in Gemfile
require 'factory_girl'
# deal with Devise
require "rails/application"
Spork.trap_method(Rails::Application, :reload_routes!)
require File.dirname(__FILE__) + "/../config/environment.rb"
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
# Devise controller test helpers:
config.include Devise::TestHelpers, :type => :controller
end
end
Spork.each_run do
# deal with factory girl
Factory.definition_file_paths = [File.join(Rails.root, 'spec', 'factories')]
Factory.find_definitions
end
Please note that config.cache_classes = true need to be set to true in test environment, otherwise you may get errors from gems like FactoryGirl.
This made my model tests (specs) run quickly, and "reload" them every time I save a file and fire rspec.
EDIT: If you're running on Ruby 1.9.3 you can try out an interesting alternative: Zeus - https://github.com/burke/zeus
Use Guard to reload Spork when you update your classes Guard::Spork allows to automatically & intelligently start/reload your RSpec/Cucumber Spork server(s).
https://github.com/guard/guard-spork
http://flux88.com/2011/04/using-guard-spork-with-mongoid-devise/
From http://www.rubyinside.com/how-to-rails-3-and-rspec-2-4336.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+RubyInside+%28Ruby+Inside%29 :
A minor snafu will remain, though. If
you update app/models/person.rb, the
change won't take effect in your tests
since Spork has the old Person still
in memory. One way around this is to
edit config/environments/test.rb and
change:
config.cache_classes = true
To:
config.cache_classes = false
With more recent versions of Factory Girl, you don't need to do much. First, add FactoryGirl.reload in Spork.each_run. If you have factories with the class parameter, they should be string.
factory :my_model, class: 'MyModel' do...
instead of
factory :my_model, class: MyModel do...

Resources