This is Part 3 of the preview for "Keeping Tests Dry" at next week's erubycon.
Several people have commented with improvements to the code shown in Part 1 and Part 2. I will respond to some of these in the final installment, but first this: What if you could declare validation tests, just like you declare the validations themselves?
class ContactTest < Test::Unit::TestCase
test_validates_presence_of :name, :email
end
This is nice and DRY: all future arguments about exactly what to assert, or why, can be settled in one place--the body of the validates_presence_of
method. Here is a possible implementation:
# TODO: eliminate the dependency @tested
def self.test_validates_presence_of(*field_symbols)
field_symbols.each do |field_symbol|
field = field_symbol.to_s
define_method("test_#{field}_required") do
@tested.send("#{field}=", nil)
assert !@tested.valid?, "Validation failed due to missing required field #{field}"
field_errors = @tested.errors.on(field_symbol)
assert_not_nil field_errors, "Validation did not run on field #{field}"
error_message = ActiveRecord::Errors.default_error_messages[:blank]
assert field_errors.include?(error_message), "Incorrect validation message for field #{field}"
end
end
end
How would you improve this method? (More to follow...)