I’ve been wondering about this. What do we exactly mean by design and verification.
Should I just apply TDD to make sure my code is SOLID and not check if it’s external behaviour is correct?
Should I use BDD for verifying the behaviour is correct?
Where I get confused also is regarding TDD code Katas, to me they looked like more about verification than design; shouldn’t they be called BDD Katas instead of TDD Katas?
I reckon that for example the Uncle Bob bowling Kata leads in the end to a simple and nice internal design but I felt that most of the process was centred more around verification than design. Design seemed to be a side effect of testing the external behaviour incrementally. I didn’t feel so much that we were focusing most of our efforts on design but more on verification. While normally we are told the contrary, that in TDD, verification is a side effect, design is the main purpose.
So my question is what should I focus on exactly, when I do TDD: SOLID, external API usability, or something else?
And how can I do that without being focused on verification?
What do you guys focus your energy on when you are practising TDD?
2
TDD code katas are about learning TDD practices and how they drive design (and learning good design in that way – yes, normally this means learning how to write SOLID code).
This means that TDD is about achieving good design – but having well designed code that is not solving a problem is useless. That’s where verification comes in – this can be in many forms, BDD being one of them as one of many automated acceptance testing techniques.
Verification is about ensuring that the code written is solving the correct problem.
So, when doing TDD, focus on the design – make sure it is clean and SOLID.
But don’t forget to add unit tests and acceptance tests (and any other tests that are deemed needed).
It might be useful to see a picture:
Note that acceptance tests (i.e. verification) sit outside of the usual TDD cycle. The unit tests insure that your code works, but the acceptance tests insure that the code meets the customer’s requirements.
ATDD stands for Acceptance Test-Driven Development.
11
Verification is about ensuring that a product meets all of the requirements as they were specified. Test Driven Development, by itself, doesn’t specify the quality of the tests written, and as such, can’t guarantee that a product fully conforms to its specification. When you write your tests first, you tend to focus on producing software that is easily testable – you achieve a high amount of functional code coverage, and have an opportunity to think about what your API should look like by writing your test before you write the backing functionality.
When you are writing your tests, you should also think about verification – map your tests to your requirements, think about other code paths within your functions (achieving a higher statement or decision coverage). But TDD doesn’t say anything about these – it just says that you should write your tests first and then write the minimal amount of code to make the tests pass. Without ensuring at least full requirements coverage of your tests and greater path coverage, your tests might not be suitable for verification purposes.
> tdd is about design not verification.
I would translate this to “the benefit of tdd is good design”.
In tdd you concentrate on writing verification code.
By doing tdd (=writing tests in isolation before implementing the code) you get good design (=minimal coupling) automatically as a side effect.
Opposed to writing automated tests after implementing code you get verififcation as well but without the extra design benefit.
It is really about both, but the verification is a nice side effect which could be accomplished by writing the tests after the code. The real benefit of TDD and writing the test first is that it helps you flesh out the design by refining the design of each logical unit or business rule and building on the rest of the logical units without breaking the other units of the design and keeping them from becoming overly coupled.
For example some developers use the TDD approach almost like a “white board” where the tests and code all live in the same file initially. It gives a lot of freedom to evolve the logic with the tests, as well as test out ideas. Then as the design evolves the code is extracted out of the test module into the application itself.
The resulting tests can be used for verification as further refactoring is done.