В настоящее время происходит размах между Shoulda и Rspec. Я читал и играл вокруг честного с RSpec, но не так много с Shoulda. Я считаю, что утверждения в одной строке легче всего читать, и тест выглядит более чистым. Но когда я не могу понять, как написать конкретное утверждение в Shoulda, я переключусь на RSpec. Однако это не очень радует.Rails 3 custom validation и shoulda
Итак, вот что я сделал сегодня. Я написал некоторые пользовательские проверки для моей модели Course
. Курс имеет start_date
и end_date.
Существует несколько правил вокруг него.
start_date
иend_date
являются обязательнымиstart_date
не может быть позднее, чем сегодняend_date
не может быть доstart_date
Я знаю, что есть тихо несколько драгоценных камней, что там можно было бы сделать это для меня. Но поскольку я новичок, я подумал, что это может быть хорошей идеей сделать это сам и научиться, когда я пойду.
Так это то, что моя модель выглядит
class Course < ActiveRecord::Base
belongs_to :category
has_many :batches, :dependent => :destroy
accepts_nested_attributes_for :batches, :reject_if => lambda {|a| a[:code].blank?}, :allow_destroy => true
has_and_belongs_to_many :students, :uniq => true
validates_presence_of :name, :course_code, :total_seats
validates_uniqueness_of :category_id, :scope => [:name, :course_code]
validates :start_date, :presence => true, :course_start_date=>true
validates :end_date, :presence => true, :course_end_date=>true
end
Мои пользовательские валидация являются
class CourseEndDateValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
if object.errors[attribute].blank? && object.errors[:start_date].blank?
if value < object.start_date
object.errors[attribute] << "cannot be later than start date"
end
end
end
end
class CourseStartDateValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
if object.errors[attribute].blank?
if value < DateTime.now.to_date
object.errors[attribute] << "cannot be later than today"
end
end
end
end
И следующий мой course_spec
require 'spec_helper'require 'date'
describe Course do
context 'validations' do
it { should validate_presence_of(:name)}
it { should validate_presence_of(:course_code)}
it { should validate_presence_of(:start_date)}
it { should validate_presence_of(:end_date)}
it { should validate_presence_of(:total_seats)}
date = DateTime.now.to_date
it { should allow_value(date).for(:start_date) }
it { should_not allow_value(date - 10).for(:start_date) }
it {should allow_value(date + 10).for(:end_date)}
end
context 'associations' do
it { should belong_to(:category)}
it { should have_many(:batches).dependent(:destroy)}
it { should have_and_belong_to_many(:students) }
end
it " end date should not be before course start date" do
course = FactoryGirl.build(:course, :end_date=>'2011-12-10')
course.should be_invalid
end
end
Теперь, прежде чем я написал последний «it» block using Rspec У меня было что-то подобное в моем контексте проверки
context 'validations' do
it { should validate_presence_of(:name)}
it { should validate_presence_of(:course_code)}
it { should validate_presence_of(:start_date)}
it { should validate_presence_of(:end_date)}
it { should validate_presence_of(:total_seats)}
date = DateTime.now.to_date
it { should allow_value(date).for(:start_date) }
it { should_not allow_value(date - 10).for(:start_date) }
it { should allow_value(date + 10).for(:end_date)}
it { should_not allow_value(date - 10).for(:end_date)} # <-------------------
end
И я получил следующий отказ
Failures:
1) Course validations
Failure/Error: it { should_not allow_value(date - 10).for(:end_date)}
Expected errors when end_date is set to Fri, 9 Dec 2011, got errors: ["name can't be blank (nil)", "course_code can't be blank (nil)", "total_seats can't be blank (nil)", "start_date can't be blank (nil)"]
не уверен, что я делаю неправильно здесь. Является ли мой пользовательский код проверки неправильным или мне нужно что-то настроить, прежде чем я запустил последнее утверждение, чтобы start_date не был нулем при тестировании end_date?
Валидации отлично работают на вид. Я имею в виду, что получаю правильные ошибки проверки в зависимости от типа данных, которые я вводил. Но тест не проходит. Я смотрел на это какое-то время, но не могу понять, что именно я делаю неправильно.
Спасибо за ввод, но я подумал, что когда шаги распечатываются на консоли, они должны делать читаемые предложения. поэтому мой вывод на консоли, когда я запускаю свою спецификацию, - это что-то вроде этого. Курс дата окончания не должна быть до даты начала курса. валидации должно требовать, чтобы имя было задано. должен требовать установить курс курса ... 'Что вы предполагая, что это правильно для тех, кто читает спецификацию. Не знаю, какой подход следует придерживаться сейчас. Есть предположения? – MMinhas
С моей точки зрения, мы должны работать, чтобы сделать спецификацию и консольный вывод доступными для чтения. Но если вы не можете иметь оба (вид, почему), то вывод консоли более важен, если вы используете вывод в режиме подробного описания. Если вы используете только точки, то спецификация важнее. Но я определенно хотел бы видеть хороший читаемый вывод консоли, особенно когда тесты терпят неудачу :) –