We’re carving a bit of a niche for ourselves in the area of “rescue” projects–projects where the original developer has parted ways with the owner of the code, which is usually a bad sign for the owner. They’re usually unable to verify the quality of the code they own, much less work on it, which is where we come into the picture. In some ways I really like these projects, as it gives me a great opportunity to forge a strong and lasting relationship with a client who is genuinely in need of help. The all-but-universal frustration is the test suite we inherit. Its non-existent, for the most part. And on the occasions we talk to the original developer about it, we usually hear some variation on the theme, “We just didn’t have time to write the tests.”
Stop lying to yourself.
If you’re in a project that’s behind, or needs to move quickly, you can’t afford not to test. If you’re the only developer on the project, you really can’t afford not to test. Testing is the only thing keeping bugs from creeping up behind you as you try to forge ahead, not unlike having Bruce Campbell watching your back as a pack of rabid zombies is coming for your brains.
What you really mean when you say “I don’t have time to test” is “I don’t know how to test.” There’s nothing wrong with saying that. (You’re still wrong, but you’re getting closer to the truth.) Most web developers, even today, test by opening up a browser, navigating to the portion of the application they’re working on and manually typing input or taking some action, then looking at the result. Here’s the problem: you’re wasting your effort if you do that. If you want to repeat that test (and you ARE checking your entire application for regressions every time you deploy it, aren’t you?) you have to invest the same time performing the same steps all over again. Its what I call sadistic software methodology, where you repeatedly engage in self-flagellation every deploy, and the more successful (and bigger) your application becomes, the more pain you create for yourself.
You could be capturing all of those actions in the form of an automated test, and then the cost of running that test approaches zero. Let’s do a quick experiment using a cucumber scenario I wrote recently.
When I go to the homepage Then I should see "Business Sign Up" When I follow "Business Sign Up" And I fill in the business signup form And I press "Sign Up" Then I should see "You will receive an email within the next few minutes. It contains instructions for confirming your account" When delayed jobs are run Then "[email protected]" should receive an email with subject "Account confirmation"
Running that feature took 1.89s in cucumber, and that number is actually somewhat inflated because we have an extremely comprehensive test library with a lot of steps that have to be parsed before the test starts running. As you can see, the steps to this test are easily-read English text, and encompass directions which a human could follow. In fact, were you to write a script for a person to follow to manually test, it would look very much like the test above. So how long does it take me to do the same test manually?
When I go to the homepage Then I should see "Business Sign Up" When I follow "Business Sign Up" (29s) And I fill in the business signup form And I press "Sign Up" Then I should see "You will receive an email within the next few minutes. It contains instructions for confirming your account" (66s) When delayed jobs are run Then "[email protected]" should receive an email with subject "Account confirmation" (27s)
So the first few steps took me 29 seconds, the next few took me a total of 66s, and the last couple (which involved manually running my delayed jobs from the console and physically checking my inbox) took 27s, for a total of just over 2 minutes time. For a single test on the happy path.
And you don’t have time to test???
Question and Answer, redux
So let’s ask the question again: why aren’t you testing?
- “I don’t have time.” Wrong. I think its pretty clear that if you’re tight on time, you can’t afford not to.
- “I don’t know how.” A better answer, but still—you know how to do it in the browser, so using Behavior Driven Development in particular means that you’ve got the basics.
The real answer is: you don’t know how to express the manual steps you’d take in code. And you know what? That’s something you can fix. There are dozens of good resources on the web concerning BDD. And I’ve never done a count, but I will bet you the dozen donuts I plan on eating next week that there are hundreds if not thousands of open-source projects on github and elsewhere that have fairly comprehensive testing libraries. If you’re a beginner, I’d recommend starting with cucumber, as it seems to be an easier tool for a new tester to use to translate their manual testing process. But the important thing to remember isn’t what tool you use to test, but that you start testing. Period.
I am guilty of telling myself I don’t have time to test, because I didn’t know how to test. I had tried to do BDD, but failed.
Until I paired with Brandon for about 20 hours on a Project, I lacked the insight I needed to “to express the manual steps” (Thanks Brandon for all the help!).
I now realize how much time I save when I have good test in place. Even though I still had to learn the hard way. I can think of two seemingly simple chunks of code I wanted to write recently… that I still haven’t finished. The reason I haven’t finish yet?, because I don’t have any test to verify what I am creating and whenever I add something new it breaks.
I am now a firm believer that I write better code faster when I write good tests first, even when I have to take time to learn how to test, or write custom testing code.
Torey: I’m guilty of the same in the not-distant-enough past. :) Unfortunately testing is something that’s basically ignored in academic circles (where many people learn the core of their development skills.) It really does gel for some people when they put themselves through an “apprenticeship” of sorts, watching someone else doing it, and having it “click.”