[rspec-users] validate_presence_of

Mike Gaffney mr.gaffo at gmail.com
Thu Feb 19 00:17:50 EST 2009


Pat, not nitpicking just using your eample, which was close, but you 
missed one of the reasons we like shoulda type tests::

should_require_attributes :body, :message => /wtf/

makes you put

validates_presence_of :body, :message => "hey dude, wtf, you need a body!"

because we have a bunch of custom error messages.

Another reason for this is that while you may trust the rails guys to keep validates_presence of working, they may change HOW it works and forget a deprecation warning. Ruby isn't a compiled language so sometimes test like this do help. We had an eye opener on this a month ago when we went to edge rails. 


Finally, the shoulda tests are nice for things like column lengths and 
maximums when you are using multiple database backends because you often 
just plain forget about things like default column size differences 
between oracle and mysql, for intance pretend you're an oracle head:

Migration.up:
  t.column :name, :string

Model:
  validates_length_of :name, :maximum => 4000, :message => "We gave you 
4000 characters, what more could you type?"

Shoulda
  should_ensure_length_in_range :name, (0..4000), :long_message => "We 
gave you 4000 characters, what more could you type?"

Will pass in oracle and fail in mysql because the default size is 255 in 
Mysql and 4000 in oracle. We had a ton of these creep up on us over the 
last few years because we just plain forgot, but the shoulda macro 
exercises it and all of the assumptions so it doesn't happen any more.
 

Pat Maddox wrote:
> On Wed, Feb 18, 2009 at 6:06 PM, Zach Dennis <zach.dennis at gmail.com> wrote:
>   
>> On Wed, Feb 18, 2009 at 7:39 PM, Fernando Perez <lists at ruby-forum.com> wrote:
>>     
>>> Yi Wen wrote:
>>>       
>>>> Hello,
>>>>
>>>> according to this post:
>>>> http://blog.davidchelimsky.net/2009/1/13/rspec-1-1-12-is-released
>>>>
>>>> I should be able to write:
>>>>
>>>> describe User do
>>>>   it {should valdate_presence_of(:login)}
>>>> end
>>>>         
>>> What's the point in testing validates_presence_of for a model? It's
>>> already tested in the framework, and so readable that a quick glance on
>>> the model says it all. I would only test it if I added some bizarre
>>> behavior with procs and so on.
>>>
>>>       
>> Question for folks who don't like writing any examples for this kind
>> of thing (including scenarios/steps). If I go tuck away some behaviour
>> behind a nice declarative interface, will you not care about having
>> examples showing that your objects utilize that behaviour?
>>     
>
> That's a huge "depends" but yeah, basically.  I don't really test code
> that can't possibly break.  Declarative code like Rails validations or
> associations can't possibly break*, it can only be removed.  Don't
> remove it unless you need to then, right?
>
> I came to this conclusion re: validations/assocations by observing the
> evolution of how people write specs for them.  You start off doing
> something like:
>
> describe User do
>   it "should require a name" do
>     User.new(:name => '').should have_at_least(1).error_on(:name)
>   end
> end
>
> and after you write a bunch of those you look for a way to DRY up your
> specs a bit so you write some kind of custom matcher.  Make it nice
> and concise and you end up with shoulda macros:
>
> describe User do
>   should_require_attributes :name
> end
>
> You could literally write a couple lines of adapter code that would
> take this specification and generate the production class!
>
> def describe(klass, &block)
>   (class << klass; self; end).class_eval do
>     alias_method :should_require_attributes, :validates_presence_of
>   end
>   klass.class_eval &block
> end
>
> What does it give you?
>
> I'm looking at the shoulda examples and chuckling at how ridiculous
> the AR ones are (controller ones are nice, they use macros for stuff
> that you can't program declaratively).
>
> class PostTest < Test::Unit::TestCase
>   should_belong_to :user
>   should_have_many :tags, :through => :taggings
>
>   should_require_unique_attributes :title
>   should_require_attributes :body, :message => /wtf/
>   should_require_attributes :title
>   should_only_allow_numeric_values_for :user_id
> end
>
> and in AR (not 100% sure this makes it pass, I'm just writing, you get the idea)
>
> class Post < ActiveRecord::Base
>   belongs_to :user
>   has_many :tags, :through => :taggings
>
>   validates_uniqueness_of :title
>   validates_presence_of :body, :title
>   validates_format_of :message, :with => /wtf/
>   validates_numericality_of :user_id
> end
>
> There are two types of specification that I've found useful:
> declaration and example.  Rails association and validation macros are
> specification by declaration.  RSpec gives us specification by
> example.  Effectively this means that a class's specification is split
> between its implementation (declarative parts) and RSpec examples.
>
> If your code is specified declaratively, you don't need to write examples.
>
>   
>> Not testing things that have no logic makes sense. However, validation
>> methods have logic, it's just wrapped up behind a nice interface.
>>     
>
> Sure but can that logic break?
>
> Pat
>
> * Associations can break via changes to the db, but that will get
> caught by other specs or acceptance tests that make use of the
> associations
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>   


More information about the rspec-users mailing list