TDD – the good, bad and ugly part
What is TDD ?
Test-driven development a.k.a TDD. This is an extreme programming practice, where a developer will follow Test First Development approach. What this means is, a developer will first write a failing unit test case before writing production code, followed by the developer will write minimal production code that is mandatory to make the unit-test case pass.
This doesn’t mean, one has to write all possible unit-test cases before developing production code, the correct approach is to consider one scenario at a time and translate the idea into an unit-test case using any unit-test framework that works for you. Obviously, the test-case will fail in the first run as no code is written yet to satisfy the test-case, this is usually a good start, once you have a failing test-case, now write only required amount of code that is mandatory to make the test-case pass, once the test-case passes, its time to perform code-refactoring to clean-up any code-smells or optimize the code, remove unwanted code and ensure the code-refactoring hasn’t messed up the functionality by re-running the test-cases to see them passing again. This is called as TDD micro-cycle.
The good part of TDD
The code-written will not just work functionally, will be robust as enough test-cases has been written to bring out any failing scenarios. The best part is, this happens in the development phase as opposed to waiting for the QA folks or the customer to raise a bug and wait for a release cycle to test the fix.
Code clean-up or refactoring can be done without any fear as the unit-test cases act as a safety-net. This helps in catching any regression issues in their early stage.
Bugs or logical issues are more easier to fix if they are reported earlier. In other words, the logic used will be fresh in developer’s mind as the code was written couple of minutes back as opposed to the effort required to understand and give a fix on a code that was written 3 or 6 months back. The best part is, it is more likely that the very same developer who wrote the code will fix the code as TDD gives feedback on test-cases immediately on developer’s machine without any need for expensive test infrastructure.
Based on my Software development & Consulting experience, I can boldly say, if a major bug-fix is done that required a design-change, vast majority of the companies don’t update the High/Low Level Design documents. This demotivates the development team to refer the design documents, as the team is aware that the design document is a stale document. Now, the question that I would like to ask you is, who is the target audience for those design documents ? Yes, you are correct, the development team is the one which require the design document, but if the development team is not going to refer the design document as it isn’t updated with recent changes, the effort spent on design documents are useless beyond a point.
In TDD approach, unit-test cases acts as an active and ever up-to date low-level design document.
The bad part of TDD
It is quite common to notice, the unit-test cases are written after the production code is developed. TDD is Test First Development approach, whereas what majority of the companies follow is Test After Development. The main drawback of Test After Development approach is that, the test-cases will be written based on the production code, in case the production code has a bug, the test-cases will not point out the bug, instead it will ensure the bug is tested as a feature.
Lot of times, people mistakenly claim they are following TDD, as they think TDD is nothing but using some popular unit-test frameworks in their projects. Many people claim that they are following TDD while the reality could be that they hardly know anything about TDD.
Bottom-line, the project teams may give-up TDD as the QA team and customer will still report silly bugs which could have been caught in the development phase with unit-test cases. The main reason for this failure is, the development team isn’t trained enough or there isn’t any go to expert within the team to help them out when they are struck.
The ugly part of TDD
Today, TDD is one of the most popular buzzword in the Software Industry. Gradually many companies are shifting their focus towards TDD, typically any company that follows Agile philosophy and frameworks like SCRUM or Kanban use TDD in their engineering side. This is a very good sign, no complaints on this part.
Management’s or Client’s mantra is very simple, they want results i.e ROI, no matter you follow Waterfall or SCRUM or Kanban, etc., In order to measure efficiency, typically management uses some kind of metrics to ensure their investment will fetch the expected outcome (ROI).
Hence, I’m not surprised to notice many companies using Code Coverage as a metrics to measure the effectiveness of Unit-test cases. The very thought of using metrics isn’t bad, the real ugly part is using Code-coverage as a metrics to measure the effectiveness of test cases is where things go wrong drastically.
The idea of using code-coverage metrics for unit-test cases, pushes the developers to achieve the target forcefully, which sometimes drives them to use heavy mocking and writing useless fake test-cases with/without conscious. The test-cases that were written just to achieve code-coverage will not help the team write better code and will not help them identify bugs, which defeats the purpose of TDD. Most of these test cases will never fail, no matter what the production code does, this is one of the unknown part to management.
SCRUM or Kanban frameworks helps you achieve Agility. Agile is all about these two mantras – Inspect & Adapt and Fail Fast. Though SCRUM or Kanban helps you Inspect & Adapt on the Project Management side, what helps you Inspect and Adapt on Engineering side is Test-driven Development (TDD), BDD & ATDD. Vast majority of the companies, follow SCRUM or Kanban as a Project Management Framework but very few companies follow TDD in the true sense. Unless development teams, uses SCRUM/Kanban for Project Management and use TDD, BDD, ATDD as part of their engineering practices in the true sense, no project can claim themselves as Agile compliant. Hence, they may not get all the benefits of SCRUM/Kanban, TDD, BDD and ATDD.
Conclusion – the climax
TDD as a technology or a software development approach, is very simple to follow and it is guaranteed to give the expected benefit, there is no doubt on that part. The most important factor that is required to make TDD help your project is mindset change.
Below are my some of the suggestions to ensure TDD really helps you
- Use the trend of bugs reported over a period of 3 to 6 releases after adapting TDD to measure the effectiveness of test cases. Ideally, the bugs should reduce over time and more issues would be caught during development phase.
- Avoid using code-coverage as a metrics to measure effectiveness of test cases. If this is not avoided, this may drive developers to write fake test cases which will merely help them show code-coverage.
- Follow Test First Development as opposed to Test After Development.
- Follow SCRUM or Kanban or similar frameworks from top to bottom all the way up-to engineering practices, which includes TDD, BDD, ATDD, etc.,
This is where I help companies as an External Consultant.