We don't write tests. There just isn't time for luxuries. 27

Posted by james
on Monday, August 27
Over the last few weeks and months, I've often had the displeasure of being reminded of the common opinion that writing automated tests slows down the development process. "We just didn't have time to write tests" or "Nope, we don't have any test coverage... we just didn't have time." are common expressions of this problematic trend in software development. In order to disregard something widely accepted as being a necessary practise, writing automated tests must really take forever, right? Wrong. I call this the testing-slows-us-down argument, and, frankly, I don't buy it at all. Here's why.

Everybody Tests

Everybody has to test their code. It's just that those of us who write automated tests write code to do our testing, where non-testers use humans (themselves, usually) to manually verify correct behavior. So, we can be sure that the testing-slows-us-down argument rests on the premise that manually verifying behavior is faster than writing automated tests.

Investing Time

The two methods of testing distribute your time investment differently. Since automated tests run very quickly, the time investment is made in writing them. Running the tests is nearly instantaneous. With manual testing, it is the opposite. Designing the tests takes nearly zero time, whereas actually running the tests takes a measurable amount of time each time you need the test. So, with automated testing, you get most of your time investment out of the way at the outset. Once it's written, it's written. With manual tests, your time investment grows each time you test for something. In order for the testing-slows-us-down argument to remain valid, the total time investment made on manual testing must be less than the time investment required to write the automated tests.

In these terms, the testing-slows-us-down argument can be expressed as follows: The time it takes to write the automated tests for a feature is greater than the total time that will be spent manually testing that feature throughout the lifetime of the project.

Since one of my goals for this article is proving the "no time to test, we need to launch our product" people wrong, I want to show that this (short-sighted) argument is as, if not more, flawed than the testing-slows-us-down argument. I'm going to phrase the product-launch argument as follows: The time it takes to write the tests for a feature is greater than the total time that will be spent manually testing that feature until product launch.

Breaking Even

If it takes twenty minutes to write your automated tests, and one minute to test your feature manually, the break even point for an automated tester is when they've run their tests twenty times. After that point, automated tests become cheaper and cheaper (per test). Manual tests continue to become increasingly expensive over their lifetime. So, the testing-slows-us-down argument can be rephrased once more, making use of our new terminology: The automated testing break even point will not be reached before product launch.

Developers Developers Developers

Because the cost of manual testing grows considerably each time you run your tests, bringing on extra developers adds a multiplier to your (growing) test cost. Anytime any developer wants to merge their branch back in to trunk, they're going to have to take a look over the whole source tree to make sure they didn't break anything. This means, for the reasonably attentive developer, testing code that they didn't write - going over all of the features. It's the manual testing equivalent of running the whole test suite. Not only is this a time-consuming process, but it is incredibly error prone.

Debugging Time!

No developer can be reasonably expected to remember, and meticulously verify all of expected functionality from an application, at each check-in. That's a superhuman expectation. You might even say it's a job better suited to a machine? Seriously, though, code is interdependent. Changes in one area can have impacts all over the application. When relying on humans to verify application behavior, a lot of bugs are going to slip through the cracks.

More bugs means more time spent debugging, which, incidentally, means more time spent testing, for the manual tester. Moreover, it's not uncommon for the same bug to surface repeatedly. We've all seen it. It's called regression, and it's why us automated testers have something wonderful called regression tests.

With every bug, automated testers (like always), make a one time investment. Since automated testing is far more likely to prevent regressions than manual testing, the time benefits here are two-fold. First, once the regression test is written, it's written, and the behavior doesn't need to be repeatedly verified by hand. Second, the bug is far less likely to resurface. Manual testers may argue, here, that they are capable of adding the regression tests to their regular passes over their code, keeping the bugs out, just the same. While this may be the case for the most superhuman of individuals, the liklihood that an entire team may be capable of such incredible manual testing is very low.

So, as a general rule, I think it's safe to say that automated tests significantly reduce debugging time, by providing a much higher degree of accuracy, and acting as a powerful weapon for preventing regression.

Release Already

It seems pretty clear to me, after a thorough analysis of the testing-slows-us-down argument that its proponents are, at the least, misguided. Automated testing is at least as fast as manual testing. In writing this article, I thought a lot about why so many people have this common misconception. I think it mostly stems from one of the following.

The most common cause of this misconception is likely naivete. Many of the challenges that really bring out the best in automated testing (and, consequently, the worst in manual testing) are far more evident with bigger projects. While I maintain that automated testing is at least as fast as manual testing on all projects, it's likely that bigger projects will see much bigger benefits. The problem, here, is that big projects often start out as small ones. And, unfortunately, growing pains can cause some of the most difficult problems with keeping software working properly.

My assumption is that the ones who aren't naive are just lazy. Learning how, what, and when to write automated tests can be a difficult undertaking, but it's well worth it. Like writing the tests themselves, a little bit of up-front investment in your skillset will save you loads of time, and headache later on. So, do yourself a favor, and learn to test. You'll thank yourself for it.

Update: See my first response in a new series to some of the discussion surrounding this article.

Comments

Leave a response

  1. DanGoAugust 28, 2007 @ 06:43 AM
    Great article. To me its not just the time saving and the lower bug count that make auto-tests so great. The biggest win to me is it lets you be very brave in your re-factoring/re-design. Because you have the safety-net of being able to check that your changes didn't break anything you can make changes with impunity knowing that most of the side-effects will be caught by the tests. This offsets a cost u didn't state for auto-tests. Debugging the tests in the face of changes. Sometimes you make code changes that break the tests but are really bugs in the tests not in the code. Love the blog!
  2. macournoyerAugust 28, 2007 @ 06:36 PM
    Great article James, You nailed it with "With manual tests, your time investment grows each time you test for something" I'd also add that automated test suite are of greater value then manual one, it's impossible to cover all possible cases manually. Like DanGo said, the main reason I write test is because it allows me to refactor the code. I always find better solution when I get back to it a couple of weeks later.
  3. James GolickAugust 29, 2007 @ 11:20 AM
    The benefits of testing are countless. Testing is something that has really improved the quality of my code, overall. Not just from a reliability standpoint, either. Testing helps design, and API quality too, to name a couple of things. So, how do we convince other developers to start learning to test? It clearly benefits us all. Thanks for the comments, guys.
  4. AlOctober 03, 2007 @ 12:30 PM
    In the real world when you have an application that's proven, this is necessary. However, when you are launching a concept, you really want to take it to market and see if it works first - and in that case writing tests is indeed a luxury because you may never test it manually 20 times ever if the app is not what's really wanted ....
  5. BreckOctober 03, 2007 @ 01:05 PM
    James, you sold me. >Like writing the tests themselves, a little bit of up-front investment in your skillset will >save you loads of time, and headache later on. So, do yourself a favor, and learn to test. Do you have any good links that I can start learning how to write automated tests?
  6. cedricOctober 03, 2007 @ 01:23 PM
    I think it's a bit more complex like that. I do agree that in the end it's well worth it, no question about it. But adoption is made difficult by (1) the learning curve (writing efficient tests with good coverage is not that easy) and (2) inadequate (or perceived inadequacies in) testing suites (not talking about RoR here). I work a lot with intensive javascript apps, and I spend way more time trying to work around the problems/limitations in the testing suite (selenium) than actually writing tests.
  7. NickOctober 03, 2007 @ 01:50 PM
    I'm with Breck. I need to start testing, but haven't spent any time learning. It's something I really need to pay attention to.
  8. EricOctober 03, 2007 @ 03:09 PM
    @cedric: You don't need to use Selenium to test javascript. You can use JSunit, which as the name states is an easy to use Javascript Unit testing library. Selenium should be used for integration tests, or acceptance tests, not unit tests on your javascript code. http://www.jsunit.net/
  9. JamesOctober 03, 2007 @ 03:19 PM
    Eric: Yes! JSUnit rocks.
    And for everybody who is looking to pick up the pace of their test adoption, I have some screencasts in the works for testing beginners. Is that something that interests you guys? Would you like to beta test them? Email me.
  10. MatthewOctober 03, 2007 @ 04:26 PM
    Anyone that wants to test in Python should really check out nose (nosetests). I made a slight modification to Django so that it gets run any time a change in code is detected in my project (i.e. whenever the development server restarts). So every time I make a code change, the tests run. Combining this feature with doctests makes testing a total breeze (and confidence booster).
  11. ryanOctober 04, 2007 @ 09:13 AM
    I think part of the argument is that sometimes there are dedicated testers in a team and writing automated tests slows the _developers_ down. The testers are the ones who either manually or automatedly (?) test and submit bug reports. If I have to alternate between writing tests and writing features it's impossible to stay 'in the zone'. This of course depends on the project and the developer, just saying. :)
  12. Frank COctober 04, 2007 @ 09:18 AM
    Here's the kind of testing scenario I see all too often. At 8:00 AM: Boss: "Why haven't we deployed XYZ app to the web yet?" Programmer: "It's still being tested. There are some integration problems we're working out." Boss: "The VP of Sales wants it deployed ASAP. Get it done now." At 9:00 AM: Boss: "Why the $--$ is the web site down?!?" One tip I would add on testing is to use version control on your test scripts and coordinate them with the build you're testing. This often overlooked step can be a huge time saver.
  13. Miklos HollenderOctober 04, 2007 @ 10:05 AM
    Why actually _write_ those tests? Many tests could just be generated from a spreadsheet.
  14. JulesOctober 04, 2007 @ 10:56 AM
    With a tool like QuickCheck, time to program tests is much reduced. This means that you get to the break even point earlier.
  15. Jonathan AllenOctober 04, 2007 @ 11:02 AM
    You are making a lot of assumptions. First, there is the idea of a product launch. Many of us work on internal applications that don't get launched so much as "thrown". You write the code and you throw it into production the same day. Secondly, that the developers do the testing. At my company, unfortunately, the developers can't do the testing because the requirements are too fuzzy. The "domain experts" have to test it. Thrid, that keeping a test up to date is free. It isn't. **When the cost of updating your automated tests exceeds that of manually testing, why use autmated tests?**
  16. Robert PappasOctober 04, 2007 @ 11:35 AM
    James, you have some great points, but you've oversimplified much. 1) The cost of making an automated test is highly variable. For some objects, writing an automated test is only 2 times the cost of doing the manual test. For other objects, it's 50 times or 100 times. Objects that live at higher levels and require lots of scaffolding and mocking to test are very costly to automate. 2) There are many classes in an application that will never need to be explicitly tested 20 times in the whole life of the application. An object that has only getters and setters needs to only be tested once, if at all. 3) There are many classes in an application that can be implicitly tested via other classes. I may not write a Unit Test for some low-level object, because I know the functionality of that object will be fully exercised by the tests I'm writing for other objects. And besides low-level objects have fewer dependencies, and are less likely to ever break, and thus there is less value to testing them continusously. 4) You have to take into consideration the time value of money. Spending $20 now to save money next year had better save you at least $50 next year. BTUF (Big Test Up Front) incurrs many of the same risks as BDUF (Big Design Up Front). It assumes you are creating artifacts now that will last and not change drastically in the future. Good luck with that. 5) In general, many TDD proponents seem to believe that if writing Automated Tests for some objects is valuable, then writing Automated Tests for every object must be extremely valuable. And that's just not true. You have to pick and choose what you want to test based on your best guess as to the return-on-investment. How hard is a object to test? How valuable will that test be? What are the odds that object will be radically redesigned or deleted in the next year? 6) You said that developers who aren't naive are just lazy. You forgot the biggest category of all: Developers who are in a god-awful hurry to meet a deadline. These are VERY hard-working developers who aren't lazy at all. They account for a very large (possibly even majority) share of the development world, and that is a major barrier to taking more time up front to write automated tests. A company will give you a deadline to meet, but often not a "qualityline" to meet. And you can argue until you are blue in the face that spending more time and money now will save you time and money in the long run, but that just doesn't sell. Most companies are willing to make that trade-off if it gets something to market faster. It's called "technical debt". Technical debt has a high interest rate, but a fast growing company will be happy to pay that. Fast growing companies write lots of applications that will be "throw-away" applications, because the purpose will either die or be radically changed within a year or two as the company continues to expand and change. So, making automated tests is good. I still agree with the basic premise of the article. But you have to consider the cost of the test, the scope of the test, the usefulness of the test, the redundancy of the test, your ability to predict the future longevity of the object you are creating, your need to meet a deadline, and the company's willingness to incur technical debt by doing things fast rather than well. Other than all of that......great article. :)
  17. sheOctober 04, 2007 @ 03:50 PM
    I think this is a way too general attitude. Neither solution is the be-all-end-all wise one, and just because others disagree doesn't mean they are wrong :) The best and ultimately only way is to not write bugs! Seems the automated-test folks laugh about that, but if i see a bug in software of these test-fanatic folks, then can I laugh please? ;-)
  18. ShantiOctober 04, 2007 @ 06:41 PM
    james - you raise some great points. I bought up the topic one time after a Refresh Phoenix meeting and the general sentiment was that it's not as much "fun" to write tests. Sometimes I think that's true. So when you're just starting out (say on your own project), if the idea of TDD'ing first doesn't seem appealing, the project simply won't get done. Also if you have any tests in a team, the whole team has to be on board with TDD and some kind of continuous integration alert system, notifying everyone when/who broke the tests, would be ideal. Otherwise one person ends up being the "test cop" and either 1) fixes everyone else's tests that broke, or 2) the tests stay broken for weeks on end! (i've seen it) she - lol. yeah what if you have a mistake in your test code & you're ensuring that the actual code passes the test (bug and all)!
  19. Paul PrescodOctober 05, 2007 @ 02:32 AM
    I am a fan of automated testing and do a lot of it, but it is certainly not a substitute for manual testing. It is prohibitively expensive to have a test suite that tests in an automated fashion that every page of a CSS and Ajax-heavy website renders correctly in all of the major browsers. You need manual testers for that.
  20. Troy DeMonbreunOctober 05, 2007 @ 12:32 PM
    Robert Pappas -- you really summed up my thoughts re: full TDD as the only way to go. My first instinct on the best ROI regarding TDD is to get coverage on the more complex, more critical pieces. 100% code coverage can be very costly, as is the cost of 100% uptime in the infrastucture realm. Anytime you have more cost, you MUST have the stakeholders buy-in. Let's face it, most stakeholders don't GET the value of QA. And unfortunately, even with 100% code coverage, if the tests aren't written well, many bugs will creep in anyway. Overall, I believe that TDD is a good thing, especially in any highly-iterative-release or high-refactoring methodology such as Agile. 100% code coverage is the clear road to low-bug code, but ask your stakeholder if they'll pay another 10+% labor and wait 10+% longer for each release. If you want it, you better sneak it into the original estimates (assuming the stakeholders will honor those anyway). James -- this really is a great article, and one of the best tools I've seen so far in the battle to convince stakeholders of the value of partial or full-throtle TDD.
  21. Aristotle PagaltzisOctober 06, 2007 @ 03:53 AM

    I think a big part of the reason that people think automated testing is expensive is because most of them lack the skill to design for testability. If you start with a big codebase that has never had any tests, it can be very, very difficult to write tests for it that achieve meaningful coverage. Usually it will require refactoring the code; so it’s a big and risky investment for what seems like an unclear benefit.

    No wonder they think it’s a waste of time.

  22. Jérôme Muffat-MéridolOctober 08, 2007 @ 05:52 AM

    The problem lies in development time planning, though...

    • Coders always make dev time estimations based on the time it will take to write (a first version of) the code. They tend not to add much time for "making it work"
    • Planners tend to address this by adding a "debugging" task, as a % of the planned task (like 20% or 33%). People spend more time debugging than writing code, though, so it should be more like 100% or 200%, but you can't have that in a project document
    • Managers sometimes double up the expected time to take this into account (and sometimes it doesn't even work out ok)

    So, well, projects end up late... They end up late because debugging time has been under-evaluated at planning stage.

    And when that big "we're late" meeting happens, who can afford to say "we're late because automated test routines took longer to write than expected ?" especially when there are big bugs in the base that the automated test routines didn't catch (Murphy's law always applies)...

    So, before you throw yourself into big amounts of automated testing, make sure you have a large "time budget" for it, make sure everybody realises that "writing the code" takes a lot less time than "making it work" ;)

  23. Keith GaughanOctober 08, 2007 @ 08:41 AM

    @Miklos Hollender: You need to write them because not all tests are simple enough to describe in a spreadsheet. That said, there's a look that does what you're talking about: Fitnesse.

  24. AngelicaOctober 22, 2007 @ 06:00 AM

    Jonathan - If the requirements are to fuzzy for the developers to test them, then how can they write any code based upon them? Do they just put some code together to see if they by cheer luck managed to understand the requirements?

  25. AngelicaOctober 22, 2007 @ 06:00 AM

    @Jonathan - If the requirements are to fuzzy for the developers to test them, then how can they write any code based upon them? Do they just put some code together to see if they by cheer luck managed to understand the requirements?

  26. EricDecember 14, 2007 @ 01:48 PM

    I agree with everything in this blog post - but unfortunately there's a few dirty little secrets in Software Development that keep preventing TDD from being adopted.

    1) The manual tests aren't always run! Perhaps the developer doesn't feel its necessary (wrong) or the doesn't know that a certain test should be run (ignorance). This was "addressed" at one of my previous employers by - I kid you not - word documents with checklists. Your Number of time spent on tests vs. time spent on tests fails to account for this, and worse yet oftentimes managers do not want developers "wasting time" on basic tests, that's what testers are for (also wrong).

    2) Delusions of Grandeur repeatedly overwhelm project schedules. Bugs? What bugs? Since your schedule doesn't include any debugging adding tests "adds time".

    3) Many managers don't care at all about quality. They pay it lip service, but time is always their chief constraint. Furthermore since the people in charge of development often have never been developers they have no insight into how it works. For example developer A and developer B write similar modules. Developer B proclaims it done two weeks before developer A, and spends the next month fixing bugs reported in testing. Developer A wrote tests as he went and has 0 bugs (contrived example). Review time comes and Developer A is often asked, "Why aren't you as fast as Developer B?" Never mind that B was actually 2 weeks later, none of that time counts.

    When told that developers don't test their code I ask "Then how do you know it works." At which point they'll say something along the lines of trying it out on their machine, so I just ask, "So why don't you automate that?" Sometimes that gets them thinking anyway.

  27. James GolickDecember 14, 2007 @ 04:13 PM

    @Eric - you're basically right. The situations you're describing don't disprove my argument, though. The fact still remains - you're spending the time, whether you like it/know it or not.

Comment






Clicky Web Analytics