Validations in rails are easy to use. Even if some custom validations have to be created, there is generic way to do it and create custom validators. The problems might appear when model instances have to be tested. Even though unit tests usually cover behavior of an instances, not validations, they are still executed in every test. Usually not to create valid objects evey time by hand, people use fixtures or factories. This way people don’t have to think about validations and tests are close to real environment (although probably validations don’t have to be tested at all or only custom ones). But the real problems appear when in order to create one valid object, lots of other objects have to be created first. This is fine if we check interconnections between those objects. But if not … setup becomes pretty painful. Test friendly gem aims to solve this problem. Installation is as easy as
gem install test_friendly
Here is an example of model using it:
# Fields present in model:
# first_name, last_name
class User < ActiveRecord::Base
acts_as_test_friendly
test_friendly_validations do
validates_presence_of :first_name, :last_name
end
end
Defining validations in test_friendly_validations
block makes validations work in development and production environments, but turned off in test environment. Validations will have to be turned on manually in tests. To turn User validations on, User.force_validations
method has to be used.
By default validations will be dropped before every rspec test. But other in other testing frameworks User.drop_validations
method will have to be used. This way validations can be turned off.
You also might want to test different validations in different tests. In this case you might want to turn on only specific one. Luckily test friendly gem provides this functionality as well. Here is an example:
# Fields present in model:
# first_name, last_name, new_attribute, default_field
class User < ActiveRecord::Base
acts_as_test_friendly
test_friendly_validations do
validates_presence_of :default_field
end
test_friendly_validations(:basic) do
validates_presence_of :first_name, :last_name
end
test_friendly_validations(:additional) do
validates_presence_of :new_attribute
end
end
In order to turn on only basic validations, we will have to use User.force_validations(:basic)
method. Same way we will be able to force additional validations. If tag name is not specified, then you will still be able to turn on those validations by calling User.force_validations
. No other validations will be forced in this case. But there is a way to do this. To turn on all test friendly validations that appear in blocks (no matter what tag name is), you can just use User.force_validations(:all)
method. All same method signatures work for dropping validations.
Enough with validations. Let’s now speak about callbacks. They can be same way painful. Test friendly gem turns them off during testing as well (with an ability to turn on as you need them).
# Fields present in model:
# first_name, last_name
class User < ActiveRecord::Base
include NotificationEmailSender
acts_as_test_friendly
test_friendly_callbacks do
after_create :send_notification_email
end
end
This way when user is created, notification emails won’t be sent in test environment. But if you want to test some callback specifically, User.force_callbacks
should help you. Generally speaking callbacks and validations work the same way and both are capable of using tags and be turned on/off during tests.
If you decided to turn on/off validations or callbacks all around the project in certain tests, you can benefit from TestFriendly::Global.force_validations
, TestFriendly::Global.drop_validations
, TestFriendly::Global.force_callbacks
, TestFriendly::Global.drop_callbacks
methods. They works with tags as well.
Any comments or problems with gem - please post on github