Maybe you have always thought that TDD is about making unit/micro test first… And that is true for some people, other people feel more comfortable starting the cycle with an end-to-end test… And you could be one of them.

But sometimes is not very clear how to do it, because when you are doing TDD…

You write a small test and see an error, then you write some code to make it pass, then you write a new test and you make the implementation to make it pass, etc… You are not suppose to write code until there’s a test that fail, and you don’t write a new test until the last tests is green…

But when you start with an end-to-end test…

And you follow this rule, you will write all the code, in all layers to make that test pass, ending with code that is all tested by you end-to-end test…

Then you won’t need unit test anymore, because you have a test that covers your code, and you should not write a test that already pass, right?

So, what should you do?

Two different practices…

Well I know two different practices…

  • Actually don’t write unit/micro tests.
  • Use the end-to-end test to know that everything has been correctly wired.

… And maybe something in the middle.

And as everything, this two approaches have pros and cons…

Actually don’t write unit tests…

This happens normally with people that are using a framework that already provides a way to test everything in integration. For example the “system” tests in Ruby on Rails or the “acceptance” tests in Ember.js.

This tools have made the process of testing the whole thing so easy that you can actually test business logic and edge cases at the end-to-end level.

This has the advantage that it can gives you a lot of confidence because you are testing everything!

But has the also disadvantages, like…

  • Less feedback in your internal design.
  • Slower tests.
  • High possibility of ending with code too coupled with the framework.

Actually I recommend this path just for small apps or parts of an app, that are either mostly in the server or mostly in the client, but that do not share a lot of behavior.

Using the end-to-end test to know that everything has been correctly wired…

To accomplish this you will change the TDD process a little.

First you will write your end-to-end test and watch it fail…

At this stage you have start to imagine the components that you will need to make that end-to-end pass. Now for each one of this components you can write them in a regular TDD style.

This has advantages like…

  • More feedback in the internal design
  • Your tests could be faster (depending in how decoupled you components are from slow things like databases and big libraries)

But has the disadvantage of not having every path tested at the end-to-end level, although in reality this will be hard even in the previous method.

I think that this method scales better, and I have seen that is what most people do, but depends much more in your ability to design the components that take place in a feature.

More about this…

I have an article that you could use if you need some guide on how to write your feature specs or end-to-end tests.

I don’t really use a lot of end-to-end tests in my TDD workflow… I normally do TDD on unit/micro tests for my use case functions and for a more focused integration tests for the adapters of the use case functions… Then for some important features I write end-to-end tests after…

… But I have used the end-to-end tests in the TDD workflow in the past, and I know that some people fill very comfortable with it. I think that is good for everyone to try it at least once =)

Also if you want to know more about end-to-end tests on the TDD cycle you can read more about it from the guys at thoughtbot, and specially in the book Growing Object Oriented Software Guided by Tests.