In this post, I intend to briefly talk about how I approach testing our production apps. This might seem obvious to some of you, dear readers, but I would like to emphasize the importance of testing your code: You should always write tests because they will help you find bugs before release, and you most certainly don’t want your end users to catch those bugs if you are in any kind of serious software business. Furthermore, a wide ranging set of test suites give you the assurance that when you develop a new feature, it doesn’t break another one developed n months/years earlier. Hence, the integration of your app is maintained. General rule of thumb is, the more tests you write, the better.
Over the years, my learnings & experiences have formed an opinion about testing, that I still hold till date. Let me start off by saying that I don’t do TDD religiously. After I develop the smallest unit of a feature (usually a task, or a user story if its small), I write enough unit test to verify this standalone unit of code/logic/biz [model|obj] does what it’s supposed to do, as described in the specs. Once I reach a certain level of confidence, then I move straight on to writing much (and by that, I mean a lot of) integration tests to ensure it blends with other components just fine, and that it doesn’t break any other functionality, etc. In other words, make certain this newly introduced component not only fulfils the requirement in isolation, but also plays well with the existing logic in place. So far, this combination has had me covered pretty well, and has resulted in very good quality products.
Talking about Rails specifically, I use MiniTest for unit, and Capybara for integration tests, as well as fixtures, of course. You might have noticed here, that I didn’t talk about controller tests, and that’s because (in my humble opinion) the C in MVC has traditionally played an orchestrating role, and should not bear any business logic. And when there is no logic, there is little need to test anything really. Integration tests check the overall flow of the app, which should already cover your controllers.
In practice, this approach has worked for me reasonably well so far.
Let me know what you think. :) Cheers!