Why I Write Automated Tests For My Code

I started my journey of unit testing my code about 4 years ago… I had played with nunit prior to that, but I never understood the point and would delete my tests after I got them to pass… that was a long time ago, and of course I’m much more educated and experienced now. :) One of the interesting things that I’ve noticed in myself over the years, concerning tests, is a change in why I write tests for my code. I’m not sure I could articulate all the various reasons that have come and gone since I started this journey, so I won’t try to do that. Rather, I wanted to note why I test, currently.

I have one overarching reason that I want to write automated tests for my code. This one reason sums it up for me and encapsulates all of the other reasons that I current have, have had in the past, and will ever have. It’s a meta-reason, really… one that allows me to change the specifics of how I test and the reasons for implementation details without having to question why I am testing.

I’m Not Smart Enough To Get It Right The First Time

That’s it. That’s why I write automated tests for my code. I know I’m not smart enough to get it right the first time because I have empirical evidence from 10+ years of software development without automated tests. I release bugs into production… that’s what it comes down to. Honestly, I don’t even get my tests right the first time. I have to iterate over the high level of my understanding, and slowly begin to drill down into the tests one at a time, filling in the test implementation and then the actual code implementation as I go. Even with all my effort to do things right and get it done right as quickly and effectively as possible, I still screw things up. The good news is that I usually have tests in place that tell me I screwed something up before the code gets committed to source control.

Now, I know I’m not perfect still and I won’t claim anything asinine like ‘tests help me write perfect code’. I still create bugs because I’m not perfect and my tests don’t always cover every possible combinatorial execution path in my code. That’s just unreasonable. (side note: I still claim 100% test coverage should be the default that you start with, not something that you work toward… but I’m smart enough to know that I’m only talking about symbol coverage, branch coverage, and simple function coverage. There are other types of code coverage that are unreasonable to write automated tests for all the time. There are also plenty of times and places where it takes a human to property test with exploratory methods that are not reasonable to do with automation.)

I don’t consider every “test” to be a test when I write it. In fact, I consider “tests” to be something that I write less and less frequently. Rather, I write specifications to show that my code is working as expected – built to specification. I write tests when I need to check for certain behavior or defects after the the implementation has been done. I’m testing to see how my code behaves in certain scenarios.

There are still other reasons that I write code with a test-first approach… but I think I’ve made my primary point abundantly clear: I’m not smart enough to get it right the first time for anything of any significance. Sure, individual lines of code, methods or even classes may be correct… but I’m talking about larger functionality groups that are meaningful to the end user… it just doesn’t happen, or happens so rarely that I consider it a statistical anomaly. Even in the world of collaborative, iterative, incremental development with wonderful customer interaction, we fail on a regular basis and still don’t get it right the first time. The difference is that we’re not yet releasing to production when we find the failures so we have the chance to fix the failures that we have found before the end user sees them.

And lastly, I want to drop a little twitter conversation into the mix, just for fun. :)


how does anyone have any faith in their own code / changes without automated tests to prove it works? #itbogglesthemind   @derickbailey Actually, without tests faith is all you are left with :)

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Agile, Behavior Driven Development, Craftsmanship, Pragmatism, Quality, Unit Testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • With any system of any reasonable complexity, it is impossible to manually test every little edge case for every page/form/view/whatever. I am so glad that I’m not the only one in this camp. I, too, write tests because I am not perfect. This is the best post I’ve read in a long time!

  • Nice post. I too think in terms of specifications (rather than tests) now. In fact, I think I’ve come to a full circle of sorts.

    If I find myself writing a test that has no resemblance to any customer requirement, then I know I have more questions for the customer to answer.

    If I find a customer requirement that has no corresponding test in the code, then I know I have more work to do in the test code base.

    I know I’m on track when there are no orphaned tests or requirements.

  • I agree with you. Very good points. Definitely I concur with the idea of writing specifications.

    Another important reason I write automated tests for my code is that it helps me to correctly design me code in a way which is simple and less coupled. When I start with the unit tests, I am compelled to separate logic into classes in order to make it easier to test.