Home > Programming > The Three Stages of Learning to Test

The Three Stages of Learning to Test

I’ve noticed three progressive stages that I’ve moved through in learning to write tests. They may not be the same for everyone, but I suspect there are some people out there who can relate. At any rate, the following stages have been my experience. By the way, I’m really talking about unit / integration testing, rather than functional testing, or (since those terms can be quite muddy) about testing done by programmers rather than testers.

Stage 1: Testing because you have to

To begin with, a lot of people write tests because their place of work says they have to. For others (like me) it may be because a lot of people online keep going on about it. In my case, this also lead me to attempt to introduce it as a standard at work, even though I was just starting out with it myself.

Often during this stage, testing can be a bit of a chore. Part of the reason may be because you don’t really (deeply) understand what you’re doing, and so you make a lot of mistakes. Your tests are just plain wrong. For example, you might mock too much or too little, making your tests fragile.

But this is a natural learning process to me. There’s certainly nothing wrong with adopting something simply because most of the industry says it’s a best practice, especially when you don’t know any better. Once you’ve mastered it yourself, you’re then in a position to decide whether to retain it, or to tweak the process. It’s much better to adopt something you don’t understand than to ignore it for the same reason.

Stage 2: Testing to spot regressions

Once you start writing tests in an automated and repeatable manner, one of the first benefits you notice is indication of regression. If you refactor a method, you can be sure it still behaves in the same way if you have some test coverage. Additionally, you might also get tests complaining if you make a change to one class, and it breaks another (assuming you haven’t mocked out too much, or have integration as well as unit tests).

This is where some sort of continuous integration starts to become important (i.e. running the tests frequently – preferably on every checkin), especially in teams with more than a handful of developers, because the tighter your feedback loop becomes, the easier it is to track down the cause of the issue.

Stage 3: Testing to see if your code works

I started programming around the age of 10. While it was obviously a long time before I did much professionally, I’ve still always needed to see if the code I’ve written actually works. Until a couple of years ago, I’d usually achieve this by somehow running the program. This makes sense for something simple, but anything more complex can lead to the need for complicated (and often ad-hoc) testing rigs, or large amounts of time trying to get the application into the desired state.

Nowadays I often simply write a test. It’s a subtle change, but my brain process is not “I should write a test because it’s a best practice”, or “I should write a test in case something breaks this later”, but “I should write a test to see if this bit of code actually does what I want it to do”. I guess it took a long time to break down those years of habitually trying to run the code to see if it worked.

This stage is really what most people call Test Driven Development. Some would argue that if you just learnt to do “test first”, and to always write tests, you’d skip straight to this point. I tend to think you can still be in stage 1 even if you’re writing your tests first, and it’s not always practical – or even necessary – to write tests for everything. There are a lot of people who get pretty fanatical when it comes to testing… I guess I’m a pragmaticist at heart.

Still, I’m sure a lot of people have gone straight to stage 3. Or progressed in a different order. Or have reached further stages of Testing Enlightenment that I’m not yet aware of. If so, I’d love to hear your experiences.

Categories: Programming Tags: ,
  1. June 29, 2009 at 11:05 pm

    A pragmatic approach is best, I would agree. You have to look at the risk/return for the tests that you write as well. If it is low risk, low return, then it’s low priority to write a test. High risk + low return, or low risk + high return, you’re probably better off to write a test. High risk + High return, we’ll if you’re not writing tests for these cases, there’s really something wrong with your approach.

  2. Sid Burn
    June 30, 2009 at 10:27 am

    If you write your code and after that you write your tests, then it is not test-driven development.

    Test-Driven Development is when you first think how something should work. You first write your test, and after that, you write your code against your tests.

    This is Test-Driven development.

    I really like the concepts of Test-Driven Development, because i think this is the best way to develope. The problem is. If you never did it before, then it is harder to do it. The second problem. Many people (Boss) thinks it is wasted time because you spent time for something and you don’t write production code.

    But the point is. You always do testing. I never see anybody who write something and don’t test if it works. Lets say with some example scripts or he do the testing manual.

    Unit testing is only to make this testing automated to save time and don’t forget to test something. The last point is something that many people didn’t see.

    And if you first write your code without first planing it, it comes fast to a point where you see that you have do something wrong and that at some points code is not reusable or some others problems. If you do Test-Driven Development then you must think about it before coding. That reduces a lot of problems before starting coding.

  3. June 30, 2009 at 11:12 am

    This sounds more like learning how to *try* to test, or how to accept testing in your work.

    I don’t see that you said anything about how to test. I’ve been learning to test for years. There’s a lot to it, if you want to do it well. For instance, how do you model your product in order to perceive what could be tested? What risks to examine and which you will ignore? How do you design your oracles to detect problems that arise? What are the weaknesses of those oracles? There are no algorithms of perfect testing, so what heuristics of test design shall we use? How do you evaluate your testing? How do you teach testing to someone else?

    I could go on. One of the stages of learning to test, I think, must be the stage where you learn how to generate any arbitrary number of interesting questions about how to test, along with potential answers to those questions.

    • Mutant
      June 30, 2009 at 11:27 am

      For sure, there’s a lot more to it than I might be making out… I was mostly talking about how I’ve incorporated testing into my daily coding routine rather than actually learning how to test…

  1. January 6, 2011 at 6:21 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: