croceldon
croceldon

Reputation: 4595

Why does upgrading to Rails 3.2.1 cause multiple Rspec tests to fail?

All 211 specs in my test suite were passing fine...until I upgraded from rails 3.2 to rails 3.2.1. Now 197 of my specs fail with errors. Most of these error have the "wrong number of arguments (0 for 1)" error described below.

Example #1:

class DocumentLibrary < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title, :use => :slugged
  has_many :shelves, :dependent => :destroy
  has_many :documents, :through => :shelves
  validates :title, :presence => true, :uniqueness => true

  default_scope :order => :title
end

Spec:

  it "can be shown on the company menu" do
    dl = FactoryGirl.create(:document_library, :title => 'Test', :menu => false, :company => true)
    dl.should be_valid
  end

Fails with:

   1) DocumentLibrary can be shown on the company menu
     Failure/Error: dl = FactoryGirl.create(:document_library, title: 'Test', menu: false, company: true)
     ArgumentError:
       wrong number of arguments (0 for 1)
     # ./spec/models/document_library_spec.rb:6:in `block (2 levels) in <top (required)>'

If I place a call to the debugger before the the FactoryGirl.create line, I get:

/Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/activesupport-3.2.1/lib/active_support/dependencies.rb:252:
(rdb:1) c
/Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/activesupport-3.2.1/lib/active_support/core_ext/module/remove_method.rb:4: `' (NilClass)
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/example_group.rb:249:in `set_it_up'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/example_group.rb:200:in `subclass'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/example_group.rb:187:in `describe'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/dsl.rb:18:in `describe'
    from /Users/Jason/code/rails/teamsite/spec/models/document_library_spec.rb:4:in `<top (required)>'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `block in load_spec_files'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `map'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load_spec_files'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/command_line.rb:22:in `run'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:80:in `run_in_process'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:69:in `run'
    from /Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:10:in `block in autorun'
/Users/Jason/.rvm/gems/ruby-1.9.3-p125/gems/activesupport-3.2.1/lib/active_support/core_ext/module/remove_method.rb:4:

Example #2

class Album < ActiveRecord::Base
  belongs_to :photo_library

  validates :title, :presence => true
  validates :title, :uniqueness => {scope: :photo_library_id}
end

class PhotoLibrary < ActiveRecord::Base
  default_scope :order => :title
  has_many :albums, :dependent => :destroy

  validates :title, :presence => true
  validates :title, :uniqueness => true
end

Spec:

  before :each do
    @photo_library = FactoryGirl.create(:photo_library, title: 'Products')
    login_admin
  end

  it "destroys an album" do
    3.times { FactoryGirl.create(:album, photo_library: @photo_library) }
    visit photo_library_path(@photo_library)
    find("h3").click_link 'Delete'
    find("#notice").should have_content("Album deleted successfully")
    Album.count.should eq 2
  end

Fails with:

1) Albums destroys an album
     Failure/Error: login_admin
     ArgumentError:
       wrong number of arguments (0 for 1)
     # ./app/controllers/sessions_controller.rb:8:in `create'
     # (eval):2:in `click_button'
     # ./spec/requests/albums_spec.rb:7:in `block (2 levels) in <top (required)>'

Line 8 in my sessions_controller is:

user = User.find_by_email(params[:email])

Inspecting the params at this point shows everything (including :email) is present as it should be.

Contrasting Example #3

This spec with FactoryGirl passes fine:

  it "is unique within a library" do
    pl = FactoryGirl.create(:photo_library, title: 'Products')
    pl2 = FactoryGirl.create(:photo_library, title: 'Competitors')
    a = FactoryGirl.create(:album, title: 'Gold Series', photo_library: pl)
    na = Album.create(photo_library_id: pl.id, title: 'Gold Series')
    na.should_not be_valid
    na.title = 'Cyclone'
    na.should be_valid

    na = Album.create(photo_library_id: pl2.id, title: 'Gold Series')
    na.should be_valid
  end

The factories are defined as follows:

  factory :document_library do
    sequence(:title) { |n| "Library Title#{n}" }
  end

  factory :photo_library do
    sequence(:title) { |n| "Photo Library Title#{n}" }
  end

  factory :album do
    sequence(:title) {|n| "Album#{n}"}
  end

If I comment out the FriendlyId lines from the DocumentLibrary model, Example #1 passes. I have no idea why that makes a difference.

However, some specs still don't pass. Consider the following model (which doesn't use FriendlyId) and spec that flunks in 3.2.1:

class DrawingLibrary < ActiveRecord::Base
  validates :title, :presence => true
  default_scope order: :title 
  has_many :drawings, :dependent => :destroy
end

 it "displays in alpha order" do
  FactoryGirl.create(:drawing_library, title: 'C')
  FactoryGirl.create(:drawing_library, title: 'B')
  FactoryGirl.create(:drawing_library, title: 'A')

  ts = ''

  DrawingLibrary.all.each do |draw_lib|
    ts += draw_lib.title
  end

  ts.should eq 'ABC'
end

1) DrawingLibrary displays in alpha order
     Failure/Error: DrawingLibrary.all.each do |draw_lib|
     ArgumentError:
       wrong number of arguments (0 for 1)
     # ./spec/models/drawing_library_spec.rb:19:in `block (2 levels) in <top (required)>'

Results of: rspec spec/models/document_library_spec.rb --backtrace

 1) DocumentLibrary can be shown on the company menu
 Failure/Error: dl = FactoryGirl.create(:document_library, title: 'Test', menu: false, company: true)
 ArgumentError:
   wrong number of arguments (0 for 1)
 # ./spec/models/document_library_spec.rb:6:in `block (2 levels) in <top (required)>'

I'm using rvm with ruby 1.9.3, with Rubygems at 1.8.16. Factory Girl is at 2.6.0, with factory_girl_rails at 1.7.0. rspec-rails is at 2.8.1.

Here's what I know so far:

Can anyone point me in a direction on this? Or offer troubleshooting advice?

Here's my Gemfile:

source 'http://rubygems.org'

gem 'rails', '3.2.1'

gem 'mysql2'
gem 'dynamic_form'
gem 'friendly_id'

group :assets do
  gem 'sass-rails', "  ~> 3.2.3"
  gem 'coffee-rails', "~> 3.2.1"
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'therubyracer'
gem 'bcrypt-ruby'
gem 'capistrano'
gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"

group :test, :development do
  gem 'rspec-rails'
  gem 'launchy'
  gem 'ruby-debug19'
  gem 'database_cleaner'
  gem 'capybara-webkit'
  gem 'spork', '~> 0.9.0.rc'
  gem 'guard-spork'
end

group :development do
  gem 'fuubar'
  gem 'powder'
end

group :test do
  gem 'turn', :require => false
  gem 'capybara'
  gem 'factory_girl_rails'
  gem 'guard-rspec'
end

The only differences in Gemfile.lock after upgrading to Rails 3.2.1 are with the Rails core libraries (no testing gems changed).

Upvotes: 13

Views: 2614

Answers (5)

theodorton
theodorton

Reputation: 674

Maybe you should try to create a new gemset, in case some gems are interfering with each other.

  1. $ rvm use 1.9.3@{unique-gemset-name-here} --create Clean gemset
  2. $ bundle
  3. $ rake spec

As I've been following this for the last two days, I'm starting to think if you should just drop the 3.2.1-upgrade for now (given this is a high priority-project). Get the value out to your customer and/or users instead of spending time on 3.2.1. Someone will figure this out sometime and then you can proceed with the upgrade.

Upvotes: 0

theodorton
theodorton

Reputation: 674

In the first spec you mention could you add the following to your controller file:

def create
  puts params.inspect
  user = User.find_by_email(params[:email])
end

I think you're not getting any info from params. And as this is the login_admin function in spec, it may be that you're using a before(:each) or let-block to sign in for most of your specs, so this may be the root of the problem.

Just noticed it now :)

Upvotes: 0

user1027503
user1027503

Reputation:

It might be an obsolete syntax in your model. Replace

default_scope order: :title 

with

 default_scope :order => :title 

If I comment out the FriendlyId lines from the DocumentLibrary model, the spec above passes. I have no idea why that makes a difference

With this modification, default_scope order: :title became the last line of your model

Upvotes: 0

theodorton
theodorton

Reputation: 674

First thing you could try (which you haven't according to the list) is simply removing all data from the test DB and "resetting" your test environment. For some reason maybe your DB is full of test data, sequences aren't working and/or migrations haven't been run.

$ rake db:test:prepare

If that doesn't fix the problem, then I'd first make my FactoryGirl-definitions and calls more consistent - not to be rude, but I think I'm seeing 3-4 different variations throughout the code you posted. It also makes it harder to decode the cryptic error messages from the trace - as you're not being consistent with the calls.

Best practice definitions:

FactoryGirl.define do
  factory :document_library do
    sequence(:title) { |n| "Title #{n}" }
  end
end

Best practice building/creation:

document_library = FactoryGirl.create(:document_library, {
  title: 'A',
  visible: false
})
# or
document_library = FactoryGirl.build(:document_library)

I know you wrote it works in Rails 3.2.0 and everything is Rails 3.2.1 fault, but there probably just an issue with 3.2.1 MIXED with the version you're using of RSpec and FactoryGirls. According to the Changelog there hasn't been any changes to the ActiveRecord module in Rails 3.2.1.

Upvotes: 3

Paweł Gościcki
Paweł Gościcki

Reputation: 9594

This might not be the root cause, but since your errors hint at FactoryGirl, I'd first convert all factories (and their creation) to another (new/recommended (?)) syntax, i.e. FactoryGirl.define do ... and doclib = FactoryGirl.create(:document_library .... It might be that Factory is something different when running specs (than what it is in the console).

Upvotes: 2

Related Questions