RSpec-рельсы |Поле пароля не требует соответствующего атрибута для модели - PullRequest
0 голосов
/ 27 января 2012

У меня есть следующие спецификации:

# spec/views/users/new.html.haml

require 'spec_helper'

describe 'users/new' do
  before { assign :user, stub_model(User).as_new_record }
  before { render }

  subject { rendered }

  it { should have_selector "form input[type=\"text\"][name=\"user[email]\"]" }
  it { should have_selector "form input[type=\"password\"][name=\"user[password]\"]" }
end

Когда я запускаю его после создания формы, он жалуется на неопределенный метод 'email':

undefined method `email' for #<User ...>

Если я добавлю этот метод в User, создайте соответствующий столбец в таблице users или заглушим метод в примере, оба примера пройдены несмотря на то, что метод password по-прежнему не определен .

Почему второй пример проходит?

Спасибо.

Рубин 1,9,3;

Ruby on Rails 3.2.1;

RSpec 2.8.0;

RSpec-рельсы 2.8.1.

Ответы [ 2 ]

0 голосов
/ 29 января 2012

Хитрый вопрос.Сначала я попытаюсь объяснить поведение, которое вы наблюдаете.Тогда я буду утверждать, что это не должно быть спецификацией представления, а более подробно раскрывать альтернативу, в которую я верю. Наконец, я расскажу вам, как на самом деле можно заставить ее работать.Если посмотреть спецификацию, код зависит от модели, имеющей все атрибуты.text_field вызывает User#login для заполнения значения формы, если оно должно быть.password_field нет, потому что вы не хотите, чтобы поля вашего пароля были предварительно заполнены.Вот как они работают вне спецификаций, и это довольно ожидаемое поведение.Вот почему вы получаете поведение.

Что касается спецификаций вида, то этот не очень полезен.Две причины - (1) он не добавляет значения и (2) он хрупок:

  1. Единственное знание, указанное в этой спецификации, - это наличие двух полей ввода.Это не поможет вам управлять дизайном или узнавать поведение.Кроме того, это не защищает вас от вероятной ошибки.Единственная ошибка, которую вы можете предотвратить - это случайное удаление формы.На мой взгляд, это маловероятно.Лучше проверить, что должна делать отправка формы в интеграционном тесте (скажем, Cucumber или Steak)
  2. Из-за заглушки тест может прерваться при расширении User и представлении.Допустим, вы добавляете поле - сайт.Если вы просто добавите столбец в базу данных и в представление, тест не пройден, поскольку он пытается получить доступ к несуществующему (в заглушке) столбцу.Теперь у вас есть рабочий код, но неудачный тест.Вам придется пойти и добавить :website в заглушку.И это только один из способов сломать это.По моему опыту, часто бывает так, что спецификация представления слишком легко нарушается, когда код работает.Это двойная проблема, когда вы зависите от помощников.

Я обнаружил, что у них есть только одно значение - тестирование интерфейса не-ActiveRecord :: Object.Вы строите представление сначала с помощью макета.Когда вы закончите, вы знаете, какие методы нужны вашей модели.

Альтернатива, которую я предпочитаю, - это тестировать подобные вещи в интеграции.Я лично использую огурец, хотя стейк тоже хорошо.Это дает вам лучшее освещение и меньше хрупкости.По моим наблюдениям, спецификации в списке рассылки rspec несколько вышли из моды.Вы можете найти более подробную информацию о том, почему их избегать.Вот одна нить , в которой я разделяю некоторые мои чувства.

Наконец, если мне не удалось убедить вас отказаться от этого пути, посмотрите factory_girl .Он предоставляет аккуратный метод, называемый build_stubbed, который дает вам заглушенную модель, которую можно использовать в form_for.Хотя я использовал это пару раз, я всегда сожалел об этом позже.

Конечно, YMMV.

0 голосов
/ 28 января 2012

Как оказалось, когда Rails создает текстовое поле для атрибута модели, модель должна иметь этот атрибут.Если его нет, ActionView :: Template :: Error будет возникать при попытке визуализации формы.Однако, когда Rails создает поле пароля , модель не должна иметь соответствующего атрибута, поэтому при рендеринге формы ничего не поднимется.

Тем самым, если я укажучто какое-то представление должно иметь текстовое поле для атрибута модели, пример потребует этот атрибут.Напротив, если я укажу, что в некотором представлении должно быть поле пароля для какого-либо атрибута, в примере не будет требоваться исключение этого атрибута.

Например:

= form_for @user do |f|
  %div= f.text_field :login #=> User#login is required
  %div= f.password_field :password #=> User#password isn't requred
...