Test First Development at different test stages

Graham Cox - Mar 20 '17 - - Dev Community

This article is going to be somewhat controversial, so I apologise for that ahead of time.

I don't like Test First Development. I love Test Driven Development, but for me it only works well in certain ways.

Firstly some definitions of what I'm talking about:

  • Test Driven Development. This is the situation where you write tests for all of your code as you go, both to ensure that what you've done works and to ensure that it doesn't break in the future
  • Test First Development. This is the situation where you write the tests for your code before the code itself. Proponents of this like it because it helps to nail down the way that the code will be used before you've even written it, which can be invaluable as part of the software design.

Now, to clarify, it's only certain forms of testing that I personally do not like Test First Development. Specifically, Unit Testing.

Test First Development works fantastically when you are developing an entire system that other code - either your own or other peoples - will depend on. This might be a REST API, or an internal module, or anything. The key here is that it is a whole set of code, and that it has to have a good external API because other code will depend on it.

For me personally, Test First Development doesn't work well when doing Unit Tests, because at the time of doing Unit Tests you are still not sure exactly what the Internal architecture of your code is going to be. Couple this with my preference for static typed languages and it gets to be a lot more trouble than it's worth.

In the world of Test First Development you are meant to:

  1. Write a failing test describing the next micro-feature you are implementing, or else refactor an existing test to cover it
  2. Write just enough code to make the tests pass
  3. Refactor your code
  4. Repeat

The idea is that the software design ends up being iterative and you don't need to spend a long time up front doing costly software designs.

In reality though, my personal experience of this ends up being.

  1. Write a failing test describing the next micro-feature you are implementing, or else refactor an existing test to cover it
  2. Decide if the code you've written so far will actually fit into the next microfeature or if it needs refactoring
  3. Refactor the existing code to better fit. You need to delete the new non-compiling test so that the other tests can run to tell if things are broken
  4. Re-write the new test
  5. Write the code for the new feature
  6. Refactor your code
  7. Repeat

The extra steps in the middle of all of this are very costly, and so in reality what you end up doing is closer to:

  1. Doing a full design for the entire (sub)system on paper first. Be it UML or just some notes on a napkin.
  2. Writing the Unit tests. These will fail to compile, so the entire build is now broken, and you don't know what other tests are still passing or failing
  3. Writing all of the code that you designed at step 1

Now, this isn't how Test First Development is meant to work. It's pretty much the opposite of how it's meant to work. But in my experience - which is admittedly coloured by the languages that I use - that's how it ends up.

On the other hand though, for anything that has an external API - be it REST, GraphQL, Java or whatever - then Test First Development is fantastic. In this case, writing the tests will help nail down the way that the API works, and will help to highlight places that the API doesn't work as well as you'd expect. You then end up with a better API before you've written a single line of Production code. You then get to build your individual units inside of this API confident that the external facing portion will be good. This is what Test First Development is all about.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player