Почему обновление до Rails 3.2.1 приводит к сбою нескольких тестов Rspec?
Все 211 спецификации в моем тестовом комплекте прошли отлично... пока я не обновился с рельсов 3.2 до рельсов 3.2.1. Теперь 197 моих спецификаций терпят неудачу с ошибками. Большинство из этих ошибок имеют ошибку "неправильное количество аргументов (0 для 1)", описанную ниже.
Пример # 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
Сбой:
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)>'
Если я помещаю вызов отладчику до строки FactoryGirl.create, я получаю:
/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:
Пример # 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
Сбой:
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)>'
Строка 8 в моем session_controller:
user = User.find_by_email(params[:email])
Проверка параметров на этом этапе показывает, что все (в том числе: электронная почта) присутствует, как и должно быть.
Контрастный пример # 3
Эта спецификация с FactoryGirl проходит нормально:
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
Заводы определяются следующим образом:
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
Если я прокомментирую линии FriendlyId из модели DocumentLibrary, пропустит пример # 1. Я понятия не имею, почему это имеет значение.
Однако некоторые спецификации все еще не проходят. Рассмотрим следующую модель (которая не использует FriendlyId) и специфицирует, что flunks в 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)>'
Результаты: 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)>'
Я использую rvm с ruby 1.9.3, с Rubygems на 1.8.16. Factory Девушка находится в 2.6.0, а factory_girl_rails - 1.7.0. rspec-rails - 2.8.1.
Вот что я знаю до сих пор:
- Возврат к Rails 3.2.0 заставляет все работать снова
- Обновление до Edge Rails не устраняет проблему.
- Исходные версии rspec gems не устраняют проблему.
- Приложение работает правильно и, как ожидалось, в режиме разработки. Кажется, что затронуты только те тесты.
- Переход к рубину 1.9.2 не устраняет проблему
- Обновление до ruby 1.9.3-p125 не устраняет проблему.
- Переход от MySQL к SQLite для тестовой среды не устраняет проблему.
- Понижение уровня factory_girl_rails до 1.6.0 или даже 1.5.0 не устраняет проблему.
- Использование Factory.create(...) вместо Factory (...) не устраняет проблему
- Использование FactoryGirl.define() и FactoryGirl.create() не устраняет проблему.
- Комментируя материал FriendlyId, некоторые из спецификаций проходят (см. ниже).
- Запуск db: test: prepare (или db: reset, db: migrate) не устраняет проблему.
- Изменение всех определений/созданий FactoryGirl, которые будут согласованы, не устраняет проблему.
- Повторная установка драгоценных камней под новый гемсет rvm (или даже переустановка rvm целиком) не устраняет проблему.
- Переписывание этих тестов в Test/Unit и FactoryGirl не вызывает ошибок. Поэтому FactoryGirl может не быть проблемой.
Может ли кто-нибудь указать мне в этом направлении? Или предложите советы по устранению неполадок?
Здесь мой 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
Единственные отличия в Gemfile.lock после обновления до Rails 3.2.1 связаны с базовыми библиотеками Rails (без тестирования камней).
Ответы
Ответ 1
Первое, что вы могли бы попробовать (что у вас нет в списке) - просто удалить все данные из тестовой базы данных и "сбросить" тестовую среду. По какой-то причине, возможно, ваша БД полна тестовых данных, последовательности не работают и/или миграции не выполнялись.
$ rake db:test:prepare
Если это не устранит проблему, я сначала сделаю свои определения FactoryGirl и более последовательными вызовами - не грубый, но я думаю, что я вижу 3-4 разных варианта кода, который вы опубликовали. Это также затрудняет декодирование загадочных сообщений об ошибках из трассировки - поскольку вы не согласуетесь с вызовами.
Определения лучшей практики:
FactoryGirl.define do
factory :document_library do
sequence(:title) { |n| "Title #{n}" }
end
end
Создание/создание лучшей практики:
document_library = FactoryGirl.create(:document_library, {
title: 'A',
visible: false
})
# or
document_library = FactoryGirl.build(:document_library)
Я знаю, что вы написали, что он работает в Rails 3.2.0, и все это ошибка Rails 3.2.1, но, вероятно, есть проблема с 3.2.1 MIXED с версией, которую вы используете RSpec и FactoryGirls. В соответствии с Changelog никаких изменений в модуле ActiveRecord в Rails 3.2.1 не было.
Ответ 2
Это может быть не основная причина, но поскольку ваши ошибки подсказывают FactoryGirl, я бы сначала преобразовал все фабрики (и их создание) в другой (новый/рекомендуемый (?)) синтаксис, то есть FactoryGirl.define do ...
и doclib = FactoryGirl.create(:document_library ...
. Возможно, что Factory
что-то другое при запуске спецификаций (чем в консоли).
Ответ 3
Это может быть устаревший синтаксис в вашей модели.
Заменить
default_scope order: :title
с
default_scope :order => :title
Если я прокомментирую строки FriendlyId из модели DocumentLibrary, спецификация выше. Я понятия не имею, почему это имеет значение.
С этой модификацией default_scope order: :title
стала последней строкой вашей модели
Ответ 4
В первом спецификаторе вы можете добавить следующее к своему файлу контроллера:
def create
puts params.inspect
user = User.find_by_email(params[:email])
end
Я думаю, что вы не получаете никакой информации от params. И поскольку это функция login_admin
в spec, возможно, вы используете before(:each)
или let
-block для входа в большинство своих спецификаций, поэтому это может быть корень проблемы.
Просто заметил это сейчас:)
Ответ 5
Возможно, вам стоит попытаться создать новый гемсет, если некоторые камни будут мешать друг другу.
-
$ rvm use [email protected]{unique-gemset-name-here} --create
Очистить gemset
-
$ bundle
-
$ rake spec
Поскольку я слежу за этим в течение последних двух дней, я начинаю думать, если вам стоит просто отказаться от обновления 3.2.1 на данный момент (учитывая, что это проект с высоким приоритетом). Получите ценность для своего клиента и/или пользователей, вместо того, чтобы тратить время на 3.2.1. Кто-то когда-нибудь это выяснит, а затем вы можете продолжить обновление.