13

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:

  • Downgrading back to Rails 3.2.0 makes everything work again
  • Upgrading to Edge Rails does not fix the problem
  • Running edge versions of the rspec gems doesn't fix the problem
  • The app runs properly and as expected in development mode. Only tests seem to be affected.
  • Downgrading to ruby 1.9.2 doesn't fix the problem
  • Upgrading to ruby 1.9.3-p125 doesn't fix the problem
  • Changing from MySQL to SQLite for the test environment doesn't fix the problem
  • Downgrading factory_girl_rails to 1.6.0 or even 1.5.0 doesn't fix the problem
  • Using Factory.create(...) instead of Factory(...) doesn't fix the problem
  • Using FactoryGirl.define() and FactoryGirl.create() doesn't fix the problem
  • Commenting out the FriendlyId stuff makes some of the specs pass (see below)
  • Running db:test:prepare (or db:reset, db:migrate) does not fix the problem
  • Changing all FactoryGirl definitions/creations to be consistent doesn't fix the problem
  • Reinstalling gems under a new rvm gemset (or even reinstalling rvm entirely) doesn't fix the problem
  • Rewriting these tests in Test/Unit and FactoryGirl produces no errors. So FactoryGirl might not be the problem

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).

croceldon
  • 4,511
  • 11
  • 57
  • 92
  • Try to create a factory in a console and post here the entire error backtrace. – Simone Carletti Feb 14 '12 at 16:46
  • The factory creation worked in the console without any errors. Please see above. – croceldon Feb 14 '12 at 17:08
  • Ok, so get the trace from a test. – Simone Carletti Feb 14 '12 at 17:09
  • I've added the log output with the failing test – croceldon Feb 14 '12 at 17:28
  • I'm sorry, but the log output doesn't provide any hint. To debug the error the backtrace of the exception is required, where you get the argument error. – Simone Carletti Feb 14 '12 at 17:33
  • How do I get the backtrace? I've tried running "rspec -b", but it gives the same basic output in my original question. That said, I've added one extra line that I didn't have in my original post. Thanks for your patience on this - it's appreciated! – croceldon Feb 14 '12 at 17:41
  • Your gemfile has `ruby-debug`. Place a `debugger` call before the line in the test that causes an error, then run the file with `rspec path/to/file -d`. When the debugger starts, enter to `irb` and try to create a factory. It must fails at this point with the full backtrace. – Simone Carletti Feb 14 '12 at 18:00
  • I've added the output from that command, but it appears that ruby-debug may not be working right, either. – croceldon Feb 14 '12 at 18:43
  • The output is from ruby-debug, it's not the Factory error. You need to get the exception backtrace but it seems any help was not successful. Sorry, I give up. – Simone Carletti Feb 14 '12 at 19:19
  • What does the factory for :document_library look like? – Rob Davis Feb 15 '12 at 01:31
  • Have you tried uncommenting the ruby-debug gem to verify the issue isn't with that library? – SpoBo Feb 16 '12 at 14:44
  • I have tried commenting out ruby-deb, but it didn't make any difference. – croceldon Feb 16 '12 at 18:43
  • I'm assuming you have the Gemfile.lock committed. Can you list the changes in that file after you upgraded to 3.2.1? Also, if you haven't done a fresh `rake db:reset`, `rake db:migrate` and `rake db:test:prepare` after the migration, it might be a good time to try that. I had a similar issue working with sqlite3 but on a different rails version and that helped. – prusswan Feb 16 '12 at 18:51
  • Resetting the db didn't work. I've posted the Gemfile.lock changes after doing the upgrade. – croceldon Feb 16 '12 at 19:07
  • Looks like nothing was changed for the test dependencies, and assuming you already tested without spork running and the usual `bundle exec rspec spec`, I can only suggest the following: 1) check that the tests are still working with rails 3.2.0 if you downgrade to that again, 2) test against ruby 1.9.2 and sqlite 3 and see if you get the same results with rails 3.2.1 – prusswan Feb 16 '12 at 19:32
  • What version of Factory Girl are you using? Try updating to the latest version? – John Feb 19 '12 at 09:11
  • Can you try changing `Factory(...)` to `Factory.create(...)`? That might not fix the issue, but give it a try. – jonnii Feb 21 '12 at 14:38
  • Also, do you have an initializer in your DocumentLibrary class? – jonnii Feb 21 '12 at 14:40
  • what is also your version of rspec-rails? there were some issues with a broken `stub_model` for rspec-rails <= 2.8.0 and rails 3.2. can you post also the result of `rspec spec/models/document_library_spec.rb --backtrace `? –  Feb 21 '12 at 14:53
  • I really recommend changing from `gem 'spork'` to `gem 'spork-rails'` -- it's the recommended way to include spork now. – Paweł Gościcki Feb 21 '12 at 14:54
  • It might work a try (github.com/thoughtbot/factory_girl/issues/118). Perhaps it the way you built your sequence. As in the docs github.com/thoughtbot/factory_girl/wiki/Usage `Factory.define :document_library do sequence(:title) { |n| "Library Title#{n}" } end` –  Feb 22 '12 at 00:20
  • Did you manage to fix this? :) – theodorton May 09 '12 at 01:12
  • Never did fix it. Ended up switching to Test/Unit so I could move on... – croceldon May 09 '12 at 12:31

5 Answers5

3

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.

theodorton
  • 674
  • 1
  • 6
  • 11
  • All good advice, but it doesn't fix the problem. The code did not originally have all the variations on FactoryGirl, but accumulated them as I tried various things brought out here. They are all now consistent, but the basic error continues to occur. – croceldon Feb 22 '12 at 17:51
2

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).

Paweł Gościcki
  • 9,066
  • 5
  • 70
  • 81
0

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

  • Alas, that doesn't work either. Changing to that syntax made no difference; still the same wrong number of arguments error. – croceldon Feb 23 '12 at 04:31
  • even if you put `default_scope` in the last line at the end of your model class, the line before `end`? –  Feb 23 '12 at 08:15
  • 1
    This is backwards, you mean replace the old hash syntax with the new. But hash syntax is hash syntax and won't matter anyway. – Dave Newton Jun 26 '13 at 02:24
0

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 :)

theodorton
  • 674
  • 1
  • 6
  • 11
  • I just tried writing params.inspect to the log, and all the expect info (including :email) is present as it should be. – croceldon Feb 23 '12 at 13:49
0

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.

theodorton
  • 674
  • 1
  • 6
  • 11
  • That didn't work. I forgot to put in the original post that I tried a whole rvm implode and reinstall without any success. Good advice on maybe sticking with 3.2.0. I'm a little worried about getting left behind though. This project is going to be a web version of desktop software I've been working on for 5+ years, it'll never be done. – croceldon Feb 24 '12 at 14:20