What is Test Driven development?
Test driven development is focused on Micro-Activities (Units rather than Functional components) and we can define it as:
“a proven discipline for delivering generic, independent and autonomous components that can be safely used to assemble large, sophisticated systems efficiently”
Test driven development therefore does not include system testing and integration testing strategies as it involves Unit Testing which is prefered due to its simplicity meaning that it is easy to simulate and measure. Unit Testing is enabled by the absence of dependencies.
Writing quality tests
There are various principles for writing well structured unit test code,we will begin with FIRST principles:
- F – Fast
- I – Independent
- R – Repeatable
- S – Self Validating
- T – Thorough
Unit tests should be very fast to run since they expect simple processing from the implemented code
Unit tests should be simple to prrocess and does not depend on other unit tests
Unit Tests should produce same result as the previous time it ran.
The outcome of result should be instantly visible to the programmer
Unit tests should describe all the expectations as defined in the micro-examples
producing well-structured unit tests that fulfill the FIRST principles, does not guarantee that we have delivered a solid solution.
Methodology for writing reliable and quality code is based on clean code SOLID Principle
- S – Single Responsibility Principle
- O – Open-Closed Principle
- L – Liskov Substitution
- I – Interface Segregation Principle
- D – Dependency Inversion Principle
Single Responsibility Principle
Each unit test must have one and only one Assert statement. This means that each component must be responsible for performing only one operation
This principle states that a component should be open for extensions but closed for modification. Applied to unit tests it ensures that we will not implement a change to an existing unit test in that unit test. Instead we must write a brand new unit test that will implement the changes.
Liskov Substitution Principle
This principle provides a guide for deciding which level of abstraction may be appropriate for the solution.“If it looks like a duck and quacks like a duck but needs batteries, you probably have the wrong abstraction”
Interface Segregation Principle
Reminds us not to bloat APIs
When subsystems need to collaborate to complete a task, they should communicate through interface. If new capability becomes necessary don’t add it to the already defined interface; instead, craft a brand new interface.
Applied to unit tests, removing the bloat from the interfaces helps us craft more specific unit tests which in turn, results in more generic components.
Dependency Inversion Principle
We should control our dependencies instead of dependencies controlling us.If there is need to use another component’s services instead of being responsible for instantiating that component within the component we are building. It must be injected to our components.
Applied to unit tests, this principle helps separate the intention from the implementation. We must strive to inject only those dependencies that have been sufficiently abstracted. This approach is important in ensuring unit tests are not mixed with integration tests.