DRY in your functional and ActionMailer tests - Rails 2.0 a feature a day #7
That's right, Don't Repeat Yourself in your functional and ActionMailer tests. If you're a Test::Unit user, this will probably look familiar to you when writing Rails functional tests (for your controllers):
class PostsControllerTest < Test::Unit::TestCase
def setup
@controller = PostsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_should_not_explode
# Invariably sexy test code.
end
end
You'd probably have noticed how setup always sets the @controller, @request and @response instance variables in all your controller tests. In Rails 2.0, you can instead subclass ActionController::TestCase (in turn a subclass of Test::Unit::TestCase) in your test cases and avoid repeating the instance variable assignments.
class PostsControllerTest < ActionController::TestCase
# No need to define setup.
def test_should_not_explode
# Invariably sexy test code.
end
end
Isn't that much better?
Watch out for a gotcha though, when you actually do need to define a setup method (like when you need to setup several other things before your tests run), as Jeffrey Allan Hardy reports. The issue has been resolved on edge Rails. If you're not using edge Rails, you should remember to always call super in your setup method should you define one:
class PostsControllerTest < ActionController::TestCase
def setup
super
@user = users(:konata)
end
def test_should_not_explode
# Invariably sexy test code.
end
end
A similar subclass of Test::Unit, ActionMailer::TestCase is available for your ActionMailer unit tests as well. That means you can replace this:
class UserMailerTest < Test::Unit::TestCase
include ActionMailer::Quoting
def setup
ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []
@expected = TMail::Mail.new
@expected.set_content_type "text", "plain", { "charset" => "utf-8" }
@expected.mime_version = '1.0'
end
def test_signup
# Test code.
end
end
with this:
class UserMailerTest < ActionMailer::TestCase
def test_signup
# Test code.
end
end
For the geeks among you, check out the related changeset.
About the contributor, Michael Koziarski
Michael Koziarski, better know as nzkoz, is a long-time Rails core committer. Michael has done a signficant amount of work improving the performance of ActiveRecord for Rails 2.0 so we have him to thank for a good portion of the optimization work done on ActiveRecord. He also keeps a fairly new personal blog.