Test Driven Development (TDD) is a methodology that focuses on an iterative development cycle where the emphasis is placed on writing test cases before features or functions are written.
TDD relies on software requirements and features written out as test cases before the software is fully developed. This is done through tracking of all software development life cycle by constantly testing it against all previous test cases. This is different from a process in which software is developed first and tested later.
Test Driven Development is credited to Kent Beck for having developed or rediscovered the technique. In 2003, he stated that TDD “encourages simple design and inspires confidence”
Test Driven Development Cycle
1. TDD: Adding a test
Each feature in a Test Driven Development starts with writing a test. Because of this, the first stage of the development cycle is the creation of a new test. The test to be created should be as concise and clear as possible, testing a specific component, function or aspects of a larger feature. For example, if a user registration form is to be created, the developer can create a test that will include all aspects of registration, these aspects may include the generation of elements in the forms, the user inputs, API connection, and much more. However, it can be tedious to correctly create a single test that will cover all of these aspects or be carried out efficiently from the start.
In contrast, TDD enables the developer to write the smallest and simplest tests to meet needs of features being actively developed. Numerous tests are created until there are enough tests for all aspects of the greater functionality.
Therefore, a single test related to the user registration may be as simple as “username must not contain numerals”. To carry out these kind of tests, the developer must understand the feature’s specifications or requirements clearly through use cases or user stories. The use cases and user stories define and outline the requirements and exceptions. Therefore, the title of our first test may be “username must not contain numerals“, and its main purpose is to test whether the username entered contains a numerical value or not.
2. TDD: Confirm the test fails
After the test is created, it is important to essential and useful to ensure that the test fails. Test Driven Development methodology helps in forcing the developer to think more about the features and requirements of a section of the code. A failed test reinforces confidence in the usefulness of the test and its benefits when the developer writes the code necessary for the test to pass.
3. TDD: Write code to pass test
The next step is for the developer to write the codes necessary to pass the test. Additional or irrelevant code that is not related to the scope of the test are not needed at this stage. The codes written at this stage will likely not be entirely thorough or exhaustive, but just good enough to pass the test. The TDD process encourages continuous refactoring, which means that the code may change many times in the future.
4. TDD: Confirm the test passes
At this stage, the developer ensures that the test passes and requirements are met such that the code written to pass the test does not lead to errors for existing features.
In the example case written for the first stage, the test case “username must not contain numerals” will be passed when the username entered does not contain a numeric value and will fail when a numeric value is discovered.
5. TDD: Refactor
In this stage, even though there is a passing test, the process of writing the code that allowed the test to pass may have introduced some duplication or inconsistencies. This is completely normal and predictable, but the importance of the refactoring is to locate these problem areas and focus on simplifying the code base.
This process should also contain recurrent running of all the previous tests carried out to confirm that the developer has not accidentally introduced any other errors or changed some errors that would lead previously passed tests to fail. Most developers call this practice regression testing – which means that the functional code does not break due to new changes.
6: Repeat all steps
If everything is kept as simple as possible (use cases, tests, code changes, confirmations, etc.), the entire process, from writing failed tests to confirming passing tests to refactoring, usually only takes a few minutes. Therefore, the process is repeated over and over again, with each new test slowly increasing the entire code base and getting closer and closer to the fully realized and completed function.
Red-Green Refactoring is a condensed version of TDD that is used often, it is just another way to refer to the stages listed above.
- Red- Features the developer wants to write tests for and the failed test.
- Green- Smallest/simplest codes necessary for the test to be passed.
- Refactoring- Ways in which the written codes are improved and refactored.
Benefits of Test Driven Development
- It reduces reliance on debugging.
- User experience and requirements is highly prioritized.
- It can lead to a more modularized, flexible, and scalable code.
- It produces near zero defects as most of the expected exceptions and test cases would have been covered and passed.
- It can lead to shorter overall development cycle.
- Confidence is improved with cleaner and less complicated code.
Limitations of TDD
- Difficult to apply in all cases. TDD is great for smaller projects or small features or components of a larger project. However, writing tests for a complicated aspect that the developer may not fully understand can be challenging and almost impossible.
- TDD requires substantial time and energy in coming up with tests and writing them even if this time can be later saved in the development stage. For many developers, the time used for this may be better used in writing new code or refactoring existing ones.
- Focusing on the simplest design and not thinking ahead can lead to major refactoring.
- If the design keeps changing rapidly, the developer will need to keep changing the tests. This could lead to a substantial waste of time writing tests for features that are quickly dropped.
Test Driven Development is a software development process that can have an important role in a software development project. It provides important user experience with its test-first design values. It also produces a remarkable improvement in code quality, coupling, as well as codes that are less prone to bugs and errors. However, a major weakness of TDD may be its’ unsuitability in implementing more complicated features with no clearly defined scope or when used on larger projects.