It’s funny to me how much of a fait accompli unit tests, continuous integration and agile methodologies have become. And, how those outside the scene understand so little of the intrinsic value. The more I talk with those developers on the outside, it becomes apparent just how wide the gap has become.
You see, I was never a fan of unit tests. Never.
Like many during the dotcom boom, I cut my teeth as a web developer, surrounding myself with clients and designers. I thought I was the bees knees. Why would I bother writing tests that would have to be refactored along with my code?
Deep down, I knew there was value. I knew it. There was no way that so many talented and capable developers were advocating their use if there wasn’t some significant value-add. But writing those tests felt like going to the dentist – and damn it if I was going to go willingly.
Soon enough, I found myself cornered into writing them. I gnashed my teeth, wrote the code, and then pointed and laughed gleefully each time I was forced to refactor. “See!” “See!” I would shout emphatically, and then blithely announce that the rest of my day was now effectively gone.
Initially, I saw test writing as most newbies do – as a way to ensure my code still worked as prescribed given an ever-changing system. I had my doubts to the effectiveness of such a principle, but I kept them to myself.
Then I thought – OK, so the PM wants these tests so they can sell it to the client. Work done, tests done – acceptance tests passed. “Done done”, and all that jazz. Makes sense, right? If you’re going to go agile, you better be able to ensure you’re actually building something every sprint, rather than just tinkering away and demoing little POCs.
It soon became apparent however, that I’d seriously underestimated the practice. Most of the discussions around software development in the post-web world – such as dependency injection, inversion of control and the problem with global state (ie. statics) – started to have a lot more meaning. I could no longer use aggregation or static singletons as helpers – even if I wanted to. Everything had to be injected and mocked, and the dependencies themselves had their own unit tests. Loose coupling became less of a nice-to-have, and more of a must-have.
It all suddenly made a lot of sense. My unit tests were enforcing best-practices on me and were actually helping me create my classes. Encapsulation, separation of concerns – each class had its purpose and my tests helped ensure that they remained that way.
Of course, I still find myself refactoring. I wouldn’t be much of a coder if I didn’t. You know what though – I’m finding it a lot less painful than it used to be. Everything is a lot more compartmentalised, and the code is self-describing. It’s no wonder there are scores of developers evangelising test-driven development (and, consequently, a counter-culture warning against over-dependence on test coverage).
If you don’t write unit tests, do yourself a favour. Start.