Duplicated factory error with rspec and factory girl? - ruby-on-rails

I'm trying to reset the "sequence" in factory girl between each test I run.
(factory_girl 2.6.0 and factory_girl_rails 1.7.0)
I think that to do so, I have to reload the FactoryGirl definitions. I do it in the last lines of spec_helper.rb:
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
require "rails/application"
Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
require 'database_cleaner'
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
config.infer_base_class_for_anonymous_controllers = false
# For mailer
config.include(MailerMacros)
config.before(:each) {reset_email}
end
end
Spork.each_run do
# This code will be run each time you run your specs.
I18n.backend.reload!
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
require 'factory_girl'
FactoryGirl.definition_file_paths = [File.join(Rails.root, 'spec', 'factories')]
FactoryGirl.find_definitions
end
Adding:
FactoryGirl.definition_file_paths = [File.join(Rails.root, 'spec', 'factories')]
FactoryGirl.find_definitions
Leads me to the following error when running rspec spec/
→ bundle exec guard
Guard uses Growl to send notifications.
Guard is now watching at '/Rails/projects/MyRailsProject'
Starting Spork for RSpec
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
Spork server for RSpec successfully started
Guard::RSpec is running, with RSpec 2!
Running all specs
Exception encountered: #<FactoryGirl::DuplicateDefinitionError: Factory already registered: user>
Which seems to be a duplicated factory error, maybe it's trying to load factory girl twice, but I don't understand why.

It is trying to load all your factories twice, because you're asking it to.
Replace your call to find_definitions with
FactoryGirl.reload
which clear out existing factories, sequences etc and then call find_definitions for you

Related

capybara-webkit js: true rspec tests not able to interact with database

I have used RSpec in conjunction with Capybara and Capybara-webkit on many Rails projects and it usually works smoothly. For some reason I'm having problems configuring the js: true feature specs to work this time around. They are not interacting with the database properly. I use factory_girl and database_cleaner to manage the test db content. I have DatabaseCleaner.strategy = :truncation in database_cleaner.rb for the js: true tests but it still doesn't work. Oddly, when I put in ActiveRecord::Base.establish_connection into databse_cleaner.rb the tests work fine. Why??
Here is rails_helper.rb:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if
Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
Capybara::Webkit.configure(&:block_unknown_urls)
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
end
This is the important parts of spec_helper.rb:
ENV['RAILS_ENV'] ||= 'test'
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup'
Bundler.require
require 'pry-byebug'
require 'capybara/rspec'
require 'capybara/webkit'
require 'database_cleaner'
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
# use `describe 'Feature', type: :feature, js: true` to use this driver
Capybara.javascript_driver = :webkit
# tests use regular (faster) driver if they don't require js
Capybara.default_driver = :rack_test
Capybara::Webkit.configure do |config|
config.allow_unknown_urls
end
RSpec.configure do |config|
config.after(:suite) do
FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
end
config.include Capybara::DSL
...
This is database_cleaner.rb (located in spec/support):
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
When I change this, the tests can interact with the db properly:
config.before(:each, js: true) do
ActiveRecord::Base.establish_connection
DatabaseCleaner.strategy = :truncation
end
Why? I shouldn't have to explicitly tell it to establish a db connection.
Your question states that you're using :transaction for your js tests, but the code shows :truncation. Truncation is what you should be using for your js tests so I assume the question is a typo.
You should be using the recommended database_cleaner - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example - which detects whether truncation is needed based on the driver being used rather than the 'js: true' metadata and also uses append_after rather than just after, which is very important for test stability.
I also don't see a require 'capybara/rails' anywhere in your rails_helper or spec_helper
When you set js: true, you're essentially just using Capybara which in essence is a Selenium-driven browser request. Any code running outside the test process (like this Selenium browser request) does not see the database fixture.
Preferable to what you're doing though, is to share the data state across the Selenium web server and test the code itself.
Somewhere in Rspec.config (possibly your database_cleaner.rb), you'll want to set
config.use_transactional_fixtures = false
"Everyday Rails Testing with Rspec" has a trick that was sometimes needed for certain test scenarios where you need to share the same DB connection before Rails 5. Although it can cause other issues as pointed out in comments below:
Make a spec/support/shared_db_connection.rb file and add this content:
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

postgresql_adapter async_exec error on rails rspec test using Capybara + FactoryGirl

I'm getting this strange error when I try to run my test in rails:
postgresql_adapter.rb:592:in `async_exec': PG::UndefinedTable: ERROR: relation "users" does not exist (ActiveRecord::StatementInvalid)
I don't know if this helps but my spec_helper.rb file looks like this:
require 'rubygems'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'factory_girl_rails'
require 'database_cleaner'
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'support/mailer_macros'
require 'support/test_helper'
require 'support/factory_girl_helper'
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new app, window_size: [1600, 1200], js_errors: false
end
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.include(FactoryGirlHelper)
config.include(MailerMacros)
config.include(TestHelper)
config.before(:each) { reset_email }
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
Capybara.javascript_driver = :poltergeist
config.include Capybara::DSL
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation) # moving to before :each doesn't help
DatabaseCleaner.strategy = :truncation # moving to before :each doesn't help
end
config.around :each do |example| # refactoring as before/after with .start/.clean doesn't help
DatabaseCleaner.cleaning { example.run }
end
end
Anyone has any idea why this is happening? The application in the browser seems to be working fine.
Sounds like the schema for you test db is out of sync, you either need to run migrations on it or just reset/recreate it.
Ok I figured it out following the answer here: FactoryGirl screws up rake db:migrate process
So the problem was coming from factorygirl. I updated my Gemfile to look like this:
gem "factory_girl_rails", :require => false
And then also add this:
require 'factory_girl_rails'
to my spec_helper.rb file and that fixed all the issues both localy and on circleci :)

How do I know if Spork is running with Autotest on Rspec?

I'm running rails 3.2.11 and ruby 1.9.3
How I implemented it:
I open a terminal window and run:
spork
Here is the message I get:
Using RSpec, Rails
Preloading Rails environment
Loading Spork.prefork block...
Rack::File headers parameter replaces cache_control after Rack 1.5.
Spork is ready and listening on 8989!
I open a separate terminal and run autotest.
Autotest is still slow.(2 mn 47 seconds for 263 examples)
I am only running controller and model tests.
Here is my spec_helper:
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
require 'spork/ext/ruby-debug'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rails'
require 'capybara/rspec'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
Capybara.app_host = "#{FULL_ROOT}"
def test_sign_in(user)
session[:user_id] = user.id
end
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end

"wrong constant name" Error when using Turnip with Spork

My Turnip test is working normally, but does not work when using spork.
I debugged with pry and I found that a missing User(class constant) causes the error.
What should I do to fix?
# working (good)
bundle exec rspec spec/acceptance/features/*
# not work (bad)
bundle exec rspec spec/acceptance/features/* --drb
Here is the error when I run with the --drb option.
Failure/Error: Give a user logged in:
NameError:
wrong constant name #<Module:0x007fd40a19c680>
# spec/acceptance/steps/user_steps.rb:8:in `block (2 levels) in <module:UserSteps>'
# spec/acceptance/steps/user_steps.rb:7:in `each'
This is my spec_helper.rb.
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/dsl'
require 'capybara/rspec'
require 'capybara/rails'
require 'turnip'
require 'turnip/capybara'
require 'shoulda/matchers/integrations/rspec'
# 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}
Dir.glob("spec/**/*steps.rb") { |f| load f, true }
WebMock.disable_net_connect!(:allow_localhost => true)
Capybara.run_server = true
Capybara.app_host = 'http://localhost'
Capybara.server_port = 8000
Capybara.default_selector = :css
Capybara.javascript_driver = :webkit
OmniAuth.config.test_mode = true
RSpec.configure do |config|
# ## Mock Framework
config.mock_with :rr
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.include FactoryGirl::Syntax::Methods
config.include Capybara::DSL, turnip: true
config.include Rails.application.routes.url_helpers
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.before(:each, js: true) do
headless = Headless.new
headless.start
end
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end
This is user_steps.rb.
1. require_relative 'helper_steps'
2.
3. module UserSteps
4. include HelperSteps
5.
6. step 'users are registered :' do |table|
7. table.hashes.each do |row_hash|
8. create(:user, class_params_by_row_hash(User, row_hash))
9. end
10. end
11. end
rails 3.2.13
rspec-rails 2.11.0
rspec 2.11.0
turnip 1.1.0
spork 1.0.0rc3
I'm not sure why this problem occurs, but you can prevent it from happening. If you're wrapping your steps in modules, you don't need to pass the true wrap parameter to load. Change:
Dir.glob("spec/**/*steps.rb") { |f| load f, true }
to:
Dir.glob("spec/**/*steps.rb") { |f| load f }
This prevents this error for me.
Reference: http://www.ruby-doc.org/core-2.1.2/Kernel.html#method-i-load

Capybara javascript driver is not working (env: Rspec, Spork, Capybara, Webkit)

this is my first questions online EVER, so please comment and I'll try to update my questions to clarify.
I am quite new to web development, and is currently working on a test suite for a company project. It was working nicely up to the point when I'm trying to do an integration test on a function, which involves javascript. I tried using both webkit(bundled from git) and selenium. Webkit gave the following error message.
Wrote response false "Unable to load URL: http://127.0.0.1:56618/ because of error loading http://127.0.0.1:56618/: Connection closed"
Cleaning database...done
Received "Reset"
Started "Reset"
Finished "Reset"
Wrote response true ""
should see invalid message (FAILED - 1)
Failures:
1) Users GET /sign_in with invalid account should see invalid message
Failure/Error: visit root_path
Capybara::Webkit::InvalidResponseError:
Unable to load URL: http://127.0.0.1:56618/ because of error loading http://127.0.0.1:56618/: Connection closed
And when using Selenium, the FireFox complain about:
Your Firefox profile cannot be loaded. It may be missing or inaccessible.
Does anybody have some clue as to what might be the problem?
Thanks in advance!
my sepc_helper.rb
Spork.prefork do
...
..
.
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) { require "#{Rails.root}/db/seeds.rb" }
config.before(:each) do
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after(:each) do
if Capybara.current_driver == :rack_test
DatabaseCleaner.clean
else
DatabaseCleaner.clean
load "#{Rails.root}/db/seeds.rb"
end
end
end
end
Spork.each_run do
ActiveRecord::Schema.verbose = false
load "#{Rails.root.to_s}/db/schema.rb"
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end
I am not sure but you can try this,
Add below code in your spec_helper.rb file
require 'spork'
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 'rspec/autorun'
require 'email_spec'
# Add this to load Capybara integration:
require 'capybara/rspec'
require 'capybara/rails'
# Database Cleaner
#require 'database_cleaner'
# DatabaseCleaner.strategy = :truncation
# 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}
Spork.each_run do
end
Do one thing uncomment database cleaner.

Resources