Earlier this year, I bought a car—my first new car. Although it fills me with sanctimonious hybrid glee (it really does), it’s making me neurotic with instrument panel indicator lights. The low-tire-pressure indicator after the weather turned cold. The insistent exclamation point from the airbag computer in my seat. The glaring amber beacon from the Integrated Motor Assist battery. I’ve never had so many things go wrong with a car!
Or have I?
Incorporating automated tests into your Continuous Integration build process can feel similar. You’re suddenly presented with all these errors. Your product seems to be broken all the time. You liked it better when things were quiet and you didn’t know how bad it was.
There are two reasons I’m getting so many warnings from my car: It has more systems, more features, more computers than any car I’ve owned before; and it has more health sensors and warning lights. It’s better at knowing when it’s a little unhappy, and better at letting me know. I take care of these little maintenance tasks, and all is well. It never reaches the big, blow-up, throw-a-rod, leave-you-stranded, heartache-on-the-interstate meltdown that results from years of indifferent neglect.
Continuously run unit tests are an army of little health sensors. CI feels painful at first, but it pays off quickly. When the system under test wavers, even minutely, the tests catch it promptly and summon your attention while it is still a small, containable, inexpensive problem. (Provided they’re running frequently. Once a day is pretty infrequent. Strive to make them fast enough that you’re willing to run them every time you commit to source control.) Continuous Integration tests keep your problems on the scale of oil changes and tire pressure, instead of engine blocks and radiators.