As development with Agile methodologies has gained momentum over the past decade and a half, the software development industry and tech-dependent businesses are progressively more focused on continuous delivery; products must be constantly updated to remain competitive, and that requires creating greater efficiency in the overall development and release processes.
Extreme Programming (XP) is a methodology created with the aim to produce higher quality code, and thus, make deployments easier. TDD (Test Driven Development) was originally created as part of the Extreme Programming (XP) methodology under the name "Test First".
How Does TDD Work?
In the TDD methodology, developers write tests before writing code, as opposed to the usual practice of writing functional code, and then testing it.
Usually, when testing code, the focus is on testing the paths that testers think the user would take, what is commonly known as a "Happy Path".
TDD allows developers & testers to focus on the actual user’s requirements, while writing code to better suit those requirements.
The first step is defining the user’s requirements. From these requirements, acceptance tests (the ones that are used to determine if the code meets the user’s requirements) can be created, and work can begin on creating one single functionality. Then, a single unit test is created to meet that functionality and, as there is still no code for the test to pass correctly, the unit test would fail. The unit test is a detailed representation of the requirement. From that point on, the process to develop the code begins with the goal of ensuring that the test is successful. This precludes any tendencies to over-code or imagine a functionality that may come later, since the simple goal is to ensure that the test passes. Once the test passes and the desired functionality is complete, code refactoring is taken up using best practices. The key point is that since the unit tests have been deemed successful, any changes introduced during refactoring of code would promptly get notified as correct / incorrect when tests are re-run. This significantly optimizes the refactoring task and the overall process time. If at any point in this process, new bugs are detected, they get included in the unit tests and are followed by code development to fix them.
As with any development methodology, there are pros and cons when using TDD
Pros of TDD
TDD helps developers understand and learn the principles of modular design when writing tests for very small features. In this way, problems in the application’s architecture can be detected at an early stage of development.
Easy Refactor / Maintenance
TDD makes refactoring and maintenance much easier. As all functionality is covered by tests, any change in code that might introduce an error is easily detectable, since unit tests begin to fail. This way, developers can be sure that when they revisit prior version code, changes can be made with confidence.
When the code is modular and the changes impact smaller pieces of functionalities, the risk associated with breaking other parts of the code decreases. When maintenance is efficient and bug detection is faster, project costs decrease.
High Test Coverage / Regression Testing
Having one test for each functionality implies that maximum coverage can be attained across the entire code. When TDD is implemented correctly, regression tests follow automatically.
A best practice is to give intuitive names to the unit tests. This enables future developers to rapidly understand the purpose of the test and the related code.
TDD also ensures that only necessary code is produced, and no production code exists without its respective tests. The code that is written to successfully pass tests is the minimum possible, and over-coding is avoided.
TDD compels the team to define the functionalities as comprehensively and clearly as possible right from initial stages, as these functionalities need to be fully understood in order to start writing tests.
TDD originated from Extreme Programming, and this is methodology is oriented towards team-based development and more specifically, Pair Programming. Therefore, TDD has collaboration at its core. Anyone in the team can work on another team members' code, since tests are used to determine any issues. Tests also serve as documentation, as outlined earlier.
Cons of TDD
One of the most debated cons in the TDD process is development speed. While it’s true that starting a project with TDD is slower than starting it with conventional development, that speed improves in the long run. If release velocity is the only primary goal, TDD may not be the best option, but if the focus is on developing a quality product, TDD creates benefits both in quality and cost.
When working with TDD, maintenance of test code is essential. If the product requirements shift or vary, tests associated with the functionality need to be first re-thought and followed through with changes in implementation code. There’s always opportunity to refine or eliminate redundant tests depending of the size of the overall system.
TDD can be complicated to learn and requires practice and dedication as it represents a large change from what most software engineers are accustomed to. It can be frustrating to begin with as it seems like a time sink, but over the longer duration, this process saves a lot of development time.
It is also difficult to narrow down the tests and make them as simple as possible and this requires experience. Creating good tests is like writing good production code: focusing on metrics (code coverage, etc.) does not always indicate the quality of testing.
TDD needs involvement of the entire team and is not limited to just the developers. Either everyone in the team should adopt it, or it’s better not to attempt it. The entire team must be aware of and believe in the importance of unit testing and the TDD process. The team must maintain the unit tests correctly else things fall apart quickly, thus complicating the maintenance.
TDD is a powerful methodology to write good, sustainable code, which certainly speeds up the testing process of the entire project. When working with a team that is convinced of the benefits of using Agile methodologies and the tools offered by Extreme Programming, TDD is a great option, as in the long run, its benefits get reflected in the code quality, the delivery speed, the count & severity of issues/bugs and the final cost of the project. If, on the other hand, there are team members that doubt the efficiency of the TDD processes, and/or if the project is under time constraints, it’s usually better to deploy Scrum/Kanban methodologies, that are more flexible.