This post originated from an RSS feed registered with Ruby Buzz
by Jay Fields.
Original Post: Ruby: Validatable Tests
Feed Title: Jay Fields Thoughts
Feed URL: http://blog.jayfields.com/rss.xml
Feed Description: Thoughts on Software Development
In the comments for my most recent entry, Validatable 1.2.2 released, Jon Leighton asks: how do you recommend testing validations?
I've had this discussion before when I wrote about testing ActiveRecord validations. I've not been able to come up with a 'best practice', but I've had some fun trying out different solutions.
My latest attempt at a solution alternative is to create assertions for the framework. For example, if I were to create a Validatable framework, that framework would include ValidatableAssertions.
To create validations for the Validatable framework I wrote my ideal syntax and then figured out how to make it work. The following code was the original version for validating that a class contained a presence of validation.
class FooTest < Test::Unit::TestCase Foo.must_validate.presence_of :name end
I originally chose the above syntax because it was expressive enough to convey my intent in the code. I spent a bit of time making this syntax work, but in the end I went with a syntax that I found a bit drier, and easier to implement.
class FooTest < Test::Unit::TestCase include ValidatableAssertions
Foo.must_validate do presence_of :name format_of(:name).with(/^[A-Z]/) numericality_of(:age).only_integer(true) end end
The above code creates a test for each line in the block given to must_validate. If the Foo class does not contain a presence of validation for name, an error with the text "Foo does not contain a Validatable::ValidatesPresenceOf for name" will be raised.
Clearly this solution has limitations. Any validates_true_for validation cannot be tested using this DSL style of testing. Furthermore, any validation that uses an :if argument cannot be use this DSL, since those validations require an instance to eval the :if argument against. However, for validations that are not validates_true_for and do not rely on an :if argument, the ValidatableAssertions can replace various existing success and failure validation tests.
If you hate this idea, no worries, you can always test your classes the traditional way: creating an instance and calling the valid? method. This DSL is, of course, another tool that may or may not help you out based on the context in which you use it.
The ValidatableAssertions code is checked into Validatable core and will be available in the next gem version.