TDD – Theoretical vs Practical Application

development-processtesting

A little over a year ago I was fortunate enough to be able to take a 9 month break from work. I decided that in that time time I would hone my C# skills. I started working on a bunch of projects and forced myself to follow TDD.

It was a fairly enlightening process.

It was tough at first, but over time I learned how to write more testable code (which, as it turns out, tends to be more SOLID code) and in the process I also sharpened my OO design skill.

Now I'm back in the workforce and I'm noticing something odd.

I prefer not to follow TDD.

I find TDD slows me down and actually makes it harder to design a clean application.

Instead, I've adopted a slightly (massively) different approach:

  1. Pick a vertical slice of work
  2. Develop a functioning prototype
  3. Refactor until everything is nice and tidy
  4. Sit back an appreciate the beautifully SOLID and testable code I've written.

You may have noticed that step 1 wasn't "define the public surface of my test target" and step 2 wasn't "test the bejesus out of said public surface." You may have also noticed that none of the steps involve testing. I'm writing testable code, but I'm not testing it… just yet.

Now, I'd like to make it clear that I'm not actually foregoing any kind of testing. The code I'm writing works. It works because I'm testing it manually.

I'd also like to make it clear that I'm not foregoing all automated testing either. This is where my process is different. And this is why I'm asking this question.

TDD in theory. Not in practice.

My process has evolved a bit and I've struck a balance between TDD and no tests that I find very productive and also reasonably safe. It goes as follows:

  1. Implement a working vertical slice of work with testing in mind, but don't write any tests.
  2. If down the road (eg, a month later) that slice needs modification
    1. Write Unit Tests, Integration Tests, Behaviour Tests, etc that guarantee the slice of work is correct
    2. Modify the code
  3. If that slice doesn't need modification,
    1. Do nothing

By simply shifting the burden of writing tests from before writing the code to before modifying the code I've been able to produce much more working code. And, when I do get around to writing tests I write far fewer of them but cover nearly as much ground (higher ROI).

I like this process, but I'm concerned it might not scale well. Its success hinges on developers being diligent about writing tests before they change things. And that seems like a pretty big risk. But, TDD has the very same risk.

So, am I going to [BT]DD hell, or is this a common form of pragmatic coding and testing?

I'd like to keep working this way. What can I do to make this process work in the long term?

Note:

I am the sole developer on my projects and I am responsible for everything: Requirements gathering, design, architecture, testing, deployment, etc. I suspect this is why my process is working.

Best Answer

To make the process work in the long term I would write the tests when the code is being written.

Which may seem to contradict your approach. However you've posed the question so I'll give you my take:

You don't have to write the tests before the code. forget that purity. However you want to write the tests around that time.
Once you have got the code working, you've tweaked it a bit, got some bugs out (we're talking about a timescale of hours here), you are then at a point of maximum knowledge about what the code is doing. This is a great time to write tests that capture your knowledge.

Leaving this until later means the knowledge will (naturally) diminish over time.

It also means that should you ever leave and should anyone else take over you will not have the immediate technical debt of not having documented (through tests) what does what.

Most of all, "some day" may not come. You may either get hit by a bus or you might board the bus for new adventures.

Finally, manual testing doesn't scale and frequently doesn't cover all the devices used by the end user.

Related Topic