Test-Driven Development (TDD)
Non-completion of testing/verifications, are the major challenge why many sprints(iteration) fails or teams not able to keep up to their promises (Iteration commitments).
In Agile, test engineers or validation teams could be called real managers as they demand that functionalities should be out on time and frequently so that they could complete testing of all the developed functionalities on time thus helping team achieve their Iteration goals. But what happens when it doesn’t happens?
At the end of the Iteration you might have completed codes (what developers believes) but untested codes, not ready for Demo as per Definition of Done. – remember the Agile Principles “Working software is the primary measure of progress“.
Sometimes teams make Iterations longer (non-agile) expecting that they will be able to complete testing within Iteration or completing a demonstrable functionality takes more than one iteration. This approach compromises not only the principles of getting frequent customer feedback but also results in low team productivity. – remember the Agile Principles “Deliver working software frequently,…, with a preference to the shorter timescale.“.
As organizations are mostly certified on certain ISO/CMM level/Six Sigma process and guidelines, and they need to maintain the high quality code standards; but sometime Agile team argue quality auditors, “hey!! we are agile team, we don’t worry about number of defects or defect density, we are more worried about working code and Demo” – remember “customer satisfaction through early and continuous delivery of valuable software” is the key.
Now remember if the working software is buggy, the cost of maintenance later are much higher, that’s why Agile team/PO/Management should also be cognisant of agile principle which says, “Continuous attention to technical excellence“. But due to delivery pressure, financial reasons or scarcity of funds, many project teams ignore ;Refactoring.
How often you noticed a developer saying this?
- “We don’t know what code is suppose to do”, because either they don’t understand the requirements or correctly understand the big picture or it’s a legacy code
- “We can’t prove that our code is working without someone manually verifying that it works”
How often developers feels this?
- We need to debug the code to see what’s happening inside; many times root cause analysis takes much longer time.
- Let us write the code from scratch, can’t maintain this code.
So let’s find solution in Test-driven development and Refactoring.
Test-Driven Development (TDD)
What is TDD?
Test-driven development (TDD) is a software development process and programming practice, sometimes also called test-driven design. It’s part of a larger software design paradigm known as Extreme Programming (XP). It’s one way to think through your requirements or design before you write your functional code. Kent Beck, who is credited with having developed or ‘rediscovered’ the TDD technique, when asked, “Why does he refers to the rediscovery (not the invention) of test-driven development, he explained: The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output.
After I’d written the first xUnit framework in Smalltalk I remembered reading this and tried it out. That was the origin of TDD for me. When describing TDD to older programmers, I often hear, “Of course. How else could you program?” Therefore I refer to my role as “rediscovering” TDD.
Test-driven development can produce applications of high quality in less time than is possible with older methods.
Proper implementation of TDD requires the developers and testers to accurately anticipate how the application and its features will be used in the real world. Problems are approached in an incremental fashion and tests intended for the same unit of code must often be done many times over.
Three Laws of TDD (as per Robert Cecil Martin ‘Uncle Bob‘)
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
TDD is both an important agile requirements and agile design technique.
When we are using TDD practice, the Professional Attitude should be
- Think about the tests first
- Break the problem into smaller units
- Treat the test code on par with production code
- Have test as documentation of actual code
- No real design needed
- Takes too much time
- Too complex to learn
- TDD means write all tests first
Steps to implement TDD approach:
- The first step is to quickly add a test, basically just enough code to fail.
- Next you run your tests, often the complete test suite (automated), to ensure that the new test does in fact fail.
- You then update your functional code to make it pass the new tests.
- Then run your tests again.
- If they fail you need to update your functional code and retest.
- Once the tests pass the next step is to start over.
Now let’s combine the TDD written by developers (Developer TDD) with Acceptance TDD/BDD:
i.e. developing and running Acceptance tests (ATDD) and TDD in the case of actual application development.
Resource for reference: I recommend watching this video “What is Test Driven Development (TDD)? With an example” which I found useful.
So here is the TDD Workflow which needs to be followed
Benefits of TDD
So let’s list down what all benefits we got from whole TDD process implementations:
- We Incrementally translated the requirements to test units
- We Concentrate on requirements/tests, then concentrate on implementation
- We only wrote as much code as we needed to make the tests pass
- Our tests helped us design our code
- We had to write testable code
- We couldn’t cheat and not write the tests
- Our tests are documentation of what our code does
- We can quickly regression test our code
- We know that our code is working
- We know that our code will continue to work
As Unit Testing is very important in TDD, make sure to write automated Unit Test suit using any of the xUnit frameworks, which is available for many languages, so that tests can be executed frequently, seamlessly and easily.
Challenges with Traditional approach (Design → Implement → Test) of software development:-
- Sometimes when you are writing/modifying code, more bugs are introduced than fixed.
- Regression bugs are very common – Situation: something used to work then stops working due to some new feature or bug-fix.
- Because of the threat of Regression bug, manual testing takes a very long time. – Retesting whole product: As product gets bigger, amount of time needed to test it becomes even more bigger.
- As code grows bigger, it becomes more and more fragile. – Chance of putting in bug when you are working on new code increased.
Automate your tests and run them every time you change your code base. This will allow you to verify your application and fix any new bugs, which got introduced in the process, immediately (quicker than long testing phase at the end of development).
Refactoring is very important and is the backbone of whole TDD process.
Resource for reference: Please go through my other blog on Refactoring
TDD can be used while developing application in almost any language and using various IDE. Few of them are
– C#, VB.NET, Java, Ruby, C++
– Eclipse, Visual Studio
xUnit frameworks like
- jUnit for Java
- nUnit for C#
- cppUnit for C++
Other tools are like
- Mocking framework
- Refactoring plugins
- Continuous Integration softwares
- Dependency injection framework
@Mohammad Sami -Agile Transformation Coach
NOTE: Please note that due to some technical issues we have lost all the users comments until March 2019. We apologise for the same. Please feel free to comment and share your views.