Disclaimer: There are no rules, only guidelines. Every project and situation has its own unique needs.
Actually, that’s exactly what this article is about.
* * *
Why do we always talk about unit tests? Why is “unit tests” automatically added to the plan of any or all projects? I think it’s just because it’s an expression we’ve gotten used to hearing. There are an awful lot of “xUnit” packages nowadays.
But what is a unit test, anyway?
The idea is that you’re writing an underlying module of some big system, and it would be nice if the underlying module could be considered dependable in isolation.
However, that depends on the underlying part being something like a module, encapsulated and reusable. Deceiving ourselves into thinking it is so is a whole problem unto itself (similar to the folly of writing your own “game engine”). If you’re writing a web app, you’re probably using some existing “framework”, or even several frameworks simultaneously. Probably you’re filling in a lot of blanks, that is if you’re not writing the boilerplate yourself, and it’s likely there’s really no opportunity for your code to be elegant or even object-oriented. Very often, the only whole “units” in a web app are the web pages themselves or the functions thereof. Usually the database operations underneath those web pages can’t or won’t be used for anything else and very often the same goes for “business logic”. In other words, even if you’ve divided up your project into classes and libraries for organization, very often those classes are worthless by themselves. They don’t serve any reusable purpose, and it would be silly to “unit test” them individually.
This is not to say there’s anything wrong with that organization nor that there can’t be self-contained modules in there that deserve some unit testing. But if the overall project is such a web app, then why is “unit testing” the first thing we think of?
I think the problem is that “unit testing” is the only thing sticking in our modern vocabulary. Maybe a variety of testing processes are familiar to you if you come from a GigantaMegaCorp, but building a mere web app doesn’t need all that traditional bureaucracy. Among many small teams, testing is still an uncomfortable concept, like documentation. And, like documentation, many developers are doing it very poorly because they’re obligated without understanding why.
It doesn’t help that some of these “xUnit” tools are poorly designed and offer very unrealistic examples as if the authors themselves had created the tool without knowing what it was needed for. I feel like I shouldn’t have to point this out. If only terrible examples are provided, how many terrible uses of the tool am I going to encounter? One of the reasons I dismissed qUnit recently was that it encourages “Visual Basic thinking” by its design (also it doesn’t do what I need at all).
Anyway, what I’m getting at is that test-driven development may be a cool way to keep up with the Joneses, but “unit testing” is the wrong way to think in a lot of projects. Instead, “system tests” should be prepared. That just means you write tests that touch the outermost layer, as practical, so that effectively all of the layers get tested at once. Invoke the actual UI, or something close to it, and see if the expected result shows up in the right place. Why limit your focus to one supposed “unit” at a time when there are so many things that can go wrong? Wouldn’t it be better to cover as much code in one test as you can, especially if you don’t have unlimited time to prepare these tests? Some of those “xUnit” tools can be made to do this easily, though some are quite unsuitable, depending on the project.
This strategy implies that you should also avoid preparing a lot of fake data or other mockups. How worthwhile are a bunch of false assertions you’ll have to throw away soon? Again, this really depends on the project, but I don’t think it should be the blindly default approach.
I’ve certainly been in situations where automated testing was invaluable. (I’ve been told that the situation is now called “DevOps”.) There are times when the tests can be useful not just during development, but for years afterward. But if the tests are there just for their own sake, like that “mandatory” documentation, then they might be a waste of everyone’s time.
Please think about your automatic assignment of resources to a testing strategy that makes sense for the project. When do they need to be run, and how often, and what is it they’re meant to prove, and why? What problem are they solving, and how? Is anyone going to notice if they’re not there?
As with estimating a project, it may be that only the actual developer can provide realistic answers.
* * *
This would be a good time to mention the phrase BTTWWADI except that some people think it stands for “butt wad”.