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.

4 Comments & TrackBacks (Add yours)

The paper doll icon that precedes each comment is an idea conceived by Vanessa Tan.

Paper doll icon
What’s new on edge Rails - the pilot - redemption in a blog's Gravatar

[…] new TestCase subclasses (ActionController::TestCase, ActionMailer::TestCase) introduced in Rails 2 have a gotcha. This has […]

Posted by: What’s new on edge Rails - the pilot - redemption in a blog on January 2, 2008 7pm

Paper doll icon
Space Babies » Blog Archive » Sweeter unit tests in Rails 2.0's Gravatar

[…] only just now discovered a sweet new feature of Rails 2.0. Unit and functional tests have gotten a lot sweeter. I can now subclass ActionController::TestCase and do away with all the setup cruft that used to be […]

Posted by: Space Babies » Blog Archive » Sweeter unit tests in Rails 2.0 on March 11, 2008 7pm

Paper doll icon
joost baaij's Gravatar

Thanks, I missed this nugget!

However, in my testcases that subclass from ActionController::TestCase the setup method doesn’t seem to be executed at all. Debug output isn’t shown, the super method isn’t called. nada!

Posted by: joost baaij on March 11, 2008 7pm

Paper doll icon
Thong Kuah's Gravatar

@joost,

This is a bug in Rails, where setup is not being called, if you are using rails 2.0.2. This was fixed in revision 8442 (one revision after rails 2.0.2 was released). See http://dev.rubyonrails.org/ticket/10568

Basically, I think you might want to rake rake rails:freeze:edge REVISION=8442

Posted by: Thong Kuah on April 7, 2008 9am

You can subscribe to the RSS feed for comments on this post.

Post a comment

(required)

(required, but never displayed)


You can format your comments using XHTML. Your email address will not be displayed or used for nefarious purposes.

Only following tags are allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>