Welcome to Giant Robots Smashing Into Other Giant Robots — a weblog about development, business, design and technology — written by thoughtbot.
Brittle Tests
A friend and I were talking about the scaffold mailer tests that are generated by rails, and it got me on a bit of a rant. Here’s what you start out with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class MailerTest < Test::Unit::TestCase # ...stuff... def setup # ...more stuff... @expected = TMail::Mail.new @expected.set_content_type "text", "plain", { "charset" => CHARSET } @expected.mime_version = '1.0' end def test_invitation @expected.subject = 'Some subject' @expected.body = read_fixture('invitation') assert_equal @expected.encoded, Mailer.create_invitation(args).encoded end private # ...even more stuff for reading the fixture and doing the encoding... end |

Basically, you’re generating the email, and then comparing it to an exact copy in your fixtures directory. Not only will this fail whenever you’ve got anything interesting like the current time in body of your mail, but it’s also just a super brittle way of doing things.
Would you write a controller test that compared the rendered view to a pre-generated version in your fixtures directory. Any changes made by the designer, any typos found, anything at all would have to also be made to that fixture.
A much better way of testing emails is like such:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class MailerTest < Test::Unit::TestCase def setup # ActionMailer settings end def test_invitation user = User.find_first email = Mailer.create_invitation(user) assert_equal "admin@politiquotes.com", email.from.first assert email.to.include?(user.email) assert_match(/welcome to politiquotes/i, email.subject) assert_match(/please follow the link below/i, email.body) assert_match('http://politiquotes.com/tour', email.body) end end |

Test only those things which are necessary. You should not be testing that there are two spaces in between each sentence, but you should be testing that you have included the tour url.
This is a great rule to follow in all testing scenarios. Don’t test that the rendered view has a div with class “person” (unless your rjs depends on it), but do test that the rendered form will post to /users. Don’t test that your flash has a :notice key with “Permission denied! Please login as an administrator and try again!”, but do test that any flash key matches against /denied/. Always strive to make your tests more focused and less brittle. I guarantee, your coworkers will thank you for it.
Update: Looks like I’m not the first person to notice the ActionMailer default tests. In fact, I guess this argument is made in the Agile Web Development with Rails book (page 420-421).
About this entry
You're reading an entry on GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS, the company weblog of thoughtbot, inc.
- Author:
- Tammer Saleh
- Published:
- September 6th 07:46 PM
- Updated:
- September 30th 09:51 AM
- Sections:
- Development
thoughtbot is hiring
We are hiring web developers and web designers in both Boston and New York, NY.
What are we up to?
We built Shoulda, an eclectic set of additions to Test::Unit; Paperclip to manage uploaded files without hassle; Jester, a REST/ActiveResource client library written in Javascript, and Squirrel, an enhancement for ActiveRecord's find syntax; — amongst some other projects.

Chad (President) and Jon (CTO) co-authored a technical book titled Pro Active Record: Databases with Ruby and Rails, which explores the ins and outs of the ActiveRecord ruby library. You can buy it today at Amazon.com.
About thoughtbot, inc.
We are a small web application development consulting business, with offices in Boston, MA and New York, NY. If you're looking to find a team for your next web development project or your new web application — get in touch.
11 comments
Jump to comment form