Testing Rails Controllers: Follow-Up

October 07, 2007

Herewith, responses to my survey How Would You Test This? regarding tools and techniques folks are using to test Rails controllers, and my humble thoughts at the end.

Mike Mangino shows you how he'd write an RSpec spec for my controller, and points out the style they use on projects.

"Our goal with controller tests is to create very simple, easy to read tests that cover the entire controller. We believe strongly in one assertion per test, so we will have a larger number of small tests. Our typical pattern is to stub everything at the beginning, and then mock as necessary to validate behavior."

Pat Maddox has found "testing controllers is generally child's play, and the model is where I run into the most trouble." He offers a step-by-step tutorial for BDDing my controller from start to finish using RSpec, and concludes with

"My controllers are easy to spec because they should be easy to spec. They just take some objects and tell them to do stuff. It's what those objects do that is complex. You can use mock objects to isolate that complexity. If you don't use mock objects, then you end up with leaky abstractions that make your tests harder to understand and maintain."

Jay Fields has never been able to accept that controllers can only be functionally tested. He looks forward to the day when we can instantiate controllers anew and unit test them:

"I think part of the problem is that controllers are not Good Citizens. Controllers violate the first rule of Good Citizenship. Upon creation (Controller.new), controllers are not in a valid state. Instead, controllers depend on being initialized within the framework and having their state set post construction time. That ends up being a problem for unit testing since it requires each test to set additional state on newly created controllers."

James Herdman wrote in to say he's a "hold the onions" sort of guy who prefers real objects over mocks/stubs whenever possible.

"Avoiding the database would be nice, but sometimes it's good to hit up your models in controller testing. Sometimes the angle at which we hit our models in the controller isn't quite as we intended when writing our models, or sometimes you expose bad behavior you didn't quite realize could happen... I play by this rule of thumb when it comes to mocking and stubbing with controllers: Fake out stuff that doesn't really matter, and fake out what's directly out of you control (e.g. external resources). (The drawback is, of course, that my tests take bloody ages to run through. But I'd rather stuff go afoul on my system than in production.)"

Kevin Barnes gave a nod to the shoulda plugin and finds the nested contexts to be handy on his "large-scale Rails app (EMR w/ 120+ models)".

Jim Morris uses RSpec with mocks, and pointed out a technique he came up with to automatically test all actions within a controller using RSpec.

I appreciate the time these folks took to write up examples and opinions. Hearing how other Rails developers are going about testing controllers gave me new perspectives, and that always helps me. I hope you picked up a new idea or two along the way, or maybe even found more confidence in the approach you're using. Indeed, perhaps you realized that you're already doing what the other cool kids are doing. At the same time, I appreciate that seeing varying tools may inadvertently cause some paralysis among those folks trying to get started.

If all this left you wondering how to get started, I offer you this embarrassingly obvious, but painfully honest, experience report: Testing is 90% discipline. The hard part is actually sitting down and doing it on a regular basis, where regular basis means "as you're writing code". Whether it's before or after you write the code, with Test::Unit, RSpec, test/spec, or tomorrow's testing framework, using mocks, stubs, or neither of the above is an implementation detail. Now, the tools and techniques (the other 10%) can help you keep the discipline. So choose tools that you're comfortable using on a regular basis, regardless of what's cool, and stick with them. And then focus the energy you might otherwise be spending on the worry of whether you're doing the right thing on the thing that matters most: Making great software.

Read more posts in the blog archive »