Despite what you might have heard around the industry and on the Internet, Test Driven Development (TDD) is not dead. The practice is still alive and well, especially in this new modern agile world.
TDD is a developer-focused practice where developers, not testers, write the test before they write their code, and then they keep refactoring their code until it passes the test.
David Heinemeier Hansson, creator of Ruby on Rails, first declared TDD was dead in 2014. Hansson stated while the practice taught him to think about testing at a deeper level, he believed it was actually hurting his software designs. More recently, Microsoft’s senior software design engineer Eric Gunnerson said that while he is grateful for what TDD has taught him, it didn’t live up to his expectations. “What I’ve seen is a consistent pattern of TDD working in a laboratory setting – developers are quick to pick up the workflow and can create working code and tests during classes/exercises/katas – and then failing in the real world,” he wrote.
While the practice is not for everyone, and it depends on the development team and team members, Kelly Emo, director of life-cycle and quality product marketing at Hewlett Packard Enterprise (HPE), believes there is a misunderstanding about what TDD can and can’t do. “The Test Driven Development is dead belief is often coupled with the belief that testing as a practice is dead, and if you just speed everything up fast enough and operate lean enough, you don’t really need to spend a lot of time in pre-production testing because you are continuously delivering, rolling back, and operating at such speed that the impact is minimal,” she said.
According to Emo, what is missing in this mindset is quality. A mistake in TDD is just assuming that quality is baked in because you are moving fast, she explained.
“It is fundamentally easier to adjust when you are pushing out very small incremental implementation. You can stay closer to user sentiment, and you can stay closer to what actually works and what doesn’t. But that isn’t going to solve the fundamental technical debt issues or risk of defects,” she said.
Test Driven Development promotes the idea of understanding what you are trying to build before you start building it, according to Walter Capitani, product manager for Klocwork at Rogue Wave. “It exposes weaknesses in requirements, in the architecture, and even in your test infrastructure before you start trying to build something. The counterpoint to that is you start building something and then realize you can’t properly test it. Then you put yourself in a situation where you are going to end up releasing something that was never properly testing,” he said.
When Test Driven Development is done correctly, developers should actually be developing better code, more efficiently, according to Jason Hammon, director of product management at TechExcel. “TDD is actually beneficial to developers because the process of writing the test will help establish clear requirements, the scope of what they are creating and perhaps what interdependencies are involved with it,” he said.
How TDD enables speed and quality
Developers may be resistant to the approach because they feel like it is unnecessary work, according to Hammon, but down the line it actually results in a clearer understanding of the software, more accurate estimates, more successful sprints, less chance of complications, and better quality code.
“While at first, the practice of TDD may feel to agile teams that it is adding overhead and effort, it actually keeps the ongoing delivery more agile. With lean and continuous delivery practices, serious issues can build up that will stop the agile release train if technical debt is allowed to seep in and build up over time,” HPE’s Emo added.
TDD enables developers to create code that is always testable, and free from defects, instability, or rigidness overtime. “By reducing technical debt, code additions or changes can be included in agile sprints and release trains much more quickly,” Emo said.
Writing the tests first also confirms the requirements that developers are looking for, according to Rogue Wave’s Capitani. “Sometimes if we start with the feature, we make assumptions about requirements or we simply miss requirements because we are thinking about designing something else,” he said. “By writing the tests first, you take a deeper dive into the requirements, which leads you to have a better understanding of them once you start writing the actual feature itself.”
By building things in right from the beginning and ensuring upfront whether what they are building is right or wrong, TDD allows development teams to achieve today’s necessary speed, according to Alex Martins, advisor for continuous testing at CA Technologies. In the past, the development team would do all the work only to find out in the next sprint or release a lot of the business concepts originally thought of were no longer relevant. This resulted in a lot of unnecessary work and rework as well as a huge loss in time, Martins explained. “The market is just moving too fast. The users are changing what they want too fast. So instead of building things the old way, TDD really helps the developer focus on building what is meaningful towards their current scope right now,” he said.
The speed in TDD also comes from incremental improvement in the actual quality of the software, and the repetition of short cycles that are tuned to testing a very specific thing in greater deal to improve the cycle, according to Thomas Hooker, vice president of marketing for CollabNet.
However, that doesn’t mean that Test Driven Development is not without challenges. In an ideal world of TDD, developers verify functionality of their software features, and verify the correct behavior over time. They ensure long-term reliability of their software, according to Rogue Wave’s Capitani.
Capitani explained that the reality of TDD is that developers are not exercising the software in the way it will be used in the real world, and that is because more sophisticated tests are expensive to write, and take a lot of time. “Developer’s don’t really want to write them because they are not verifying features, they are proving the software is reliable, has no security vulnerabilities, or other things that are not directly related to the features customers are asking for,” he said. Capitani said TDD approaches need to be coupled with static code analysis solutions so it can verify the quality of the software such as looking for memory leaks, security weaknesses, and reliability issues. “You have to ensure you are reproducing the real world environment that your software is going to encounter, and not just testing that something works,” he said.
Emo added the “fox guarding the hen house” can also be a risk of TDD. In TDD, the developer that is writing the test is also writing the code to go along with that test. According to Emo, in an ideal world two individual developers would be working together — one to write the test, and one to write the code. “Often in agile teams, roles may switch off during different sprints to expand experience across pure developers and dev/testers, but during a sprint, they should be two different people working on the sprint,” she said.
According to CA’s Martins, it isn’t always feasible to have a two developer approach because from a budgeting perspective, if it is increasing the workload of another developer, it is not going to be very well received. Developers don’t want to think about adopting something new if it means adding more work, he explained. However, new tools and solutions are coming out that will help automatically generate the tests that can be used by developers to drive their application development. “This is not necessarily increasing the workload, but using better solutions and better technology that wasn’t available before,” he said.
Measuring success
The biggest challenge for teams trying to adopt TDD is figuring out how to measure that they are truly getting better, according to CA’s Martins.
There is often pushback from teams to do TDD because developers feel like it is extra work, and QA teams don’t feel like it is sufficient enough or broad enough. In addition, developers might be worried they aren’t going to write the best tests, and that maintaining them will be expensive and time consuming. However, if developers are running tests as part of an extra step in their development process, getting feedback from QA that the code quality is higher or bug rates are going down, and that it is making their cycles shorters, that is a good indication that they are on the right track, according to TechExcel’s Hammon.
“If it can be implemented, developers can do it, it is not making their work take a lot longer, and it is increasing the quality of code, that is a sign that is is beneficial,” he said.
Martins says there are four pillars that support software quality: Code quality, pipeline quality, application quality and customer experience. To visualize how they are performing throughout the lifecycle, teams should be value-stream mapping. That technique shows how much time is being spent on coding and testing, and the cost from a effort perspective and timing perspective, according to Martins.
“If you are able to showcase to the developers that they are not spending more time, but they just \ shifting the amount of time spent upfront in defining the tests, and they are just going to do it once and move on, it will help them to see why they are doing this and how they are getting better,” he said.
Successful TDD developers will not only write tests that pass, they will write tests that are comprehensive, according to Rogue Wave’s Capitani. To do so, they need to understand how software is going to interact with the rest of the work around it and have the mental skill to look for weaknesses, he said.
Developers need to sit in backlog grooming sessions and start thinking about potential flaws or potential points they have to validate before they know or think they know the code is accomplishing what was in scope, according to Martins.
“There is a mindset change that needs to happen. Developers have to start thinking about what is it that this code is suppose to do, and how will they validate that it is actually doing what it is supposed to do. They need to write the tests for each of the methods they are building, define the test, write the code for the test to pass, and then refactor until it is good enough. This helps developers focus on just writing enough code — not more, not less — so they can move onto the next task on their list knowing it will not come back to them because from their perspective they have already embedded quality,” he said.
TDD drives customer experience
The reason why software development and delivery has to move so fast is because customer expectations are changing so quickly, and that makes Test Driven Development so much more important in a modern agile software world, according to CollabNet’s Hooker.
Hooker explained users are not driven by brand loyalty, they are driven by experience loyalty. For instance, if a user is trying to catch a ride using the Uber app and the application is experiencing glitches, the user gets aggravated, and instead of continuing to try with the application, he or she will often leave the app and click on a competitor’s application like Lyft. “[Users] are driven by the experience, so when increasingly the developer’s end work touches the customer directly, developers have to have high quality assurance that the outcome is going to give the customer what they want,” he said.
Today, software drives how companies interact with customers, how customers interact with companies, and how companies drive their business. Test Driven Development is an important part of that, Hooker explained.
“We have to find every little step in our process and optimize that step to deliver high quality software that meets the needs of our customer. Once we get done doing it, we go back through the system and we find where is the next area to improve,” he said. “Test Driven Development folds very nice into our agile driven CI/CD DevOps world because it is all focused on innovating quickly, providing not just a high quality product, but a high quality experience for the customer,” he said.
The tester’s role in TDD
While Test Driven Development is very much developer focused, that doesn’t mean the software tester’s role is pushed to the side. “Test Driven Development does not replace testing, it is an addition to improve quality of code and speed,” said CollabNet’s Hooker.
TDD is just one step in the process of improving things. Applications are large and contain hundreds of thousands if not millions of lines of code involving lots of developers. There are still all sorts of things like integration testing and platform testing, and a number of different ways to test that TDD does not address so that at the end of the day, a great user experience for the customer is being delivered, Hooker explained. TDD simply just improves the process with better upfront testing and upfront quality that has the ability to propagate its way through the lifecycle.
A tester is responsible for creating automated test scripts or assets that go beyond unit or functional testing; creating tests for load, performance, and application security; and continually assessing the quality and the overall experience, according to HPE’s Emo. “There are many different roles that testing practitioners play in agile teams doing TDD. TDD is driving the building of inherently higher quality code and a dev/tester or test engineer will build the TDD test cases for the developers based off the user stories; however they may also engage in a number of other key practices in the sprint,” she said.
CA’s Martins said it is important to note that while TDD tells you whether what you built was right or wrong, it doesn’t tell you if the application is doing what it was supposed to do. To understand if you built what was intended by the business and compare how the system is working against what the requirement was originally saying it should, Acceptance Test Driven Development (ATDD) is necessary. According to Martins, ATDD addresses whether or not the application is doing what it was intended to do while TDD at the unit level addresses if the code is correct and properly working.
The testing team helps provide those acceptance tests to the developers so developers can better ensure their code is good. “Here, the testing team can help the developer early on because it is all about preventing defects, catching them as early as possible and shifting everything left as much as possible,” said Martins. “Testers are starting to be seen more as enabler for more speed in the pipeline, for better quality and not just as an entity that works against the developer.”
Testers can also use Business Driven Development (BDD) to validate the business process and the code function, and develop quality earlier, HPE’s Emo added. “BDD is designed to get people thinking about the business process and the behavior you want,” she said. “It does a nice job of shrinking down the gap between writing requirements, writing automated tests and writing code because right upfront it because your documentation.”.
A successful testing strategy needs to look at the whole cycle of what you are creating and releasing. Following a test-driven approach to make sure developers are checking in high-quality code is a good place to start and will ensure better results down the road, but having a holistic approach is also very important, according to TechExcel’s Hammon.