The Test-Driven Development (TDD) methodology was invented to improve the way we test the code we write, with the final goal of increasing the quality of systems being implemented. The basic idea is that the tests must be written before the code, and following the same requirements. In practice, adopting the TDD approach really caused an improvement in quality, even if in general the total development time also increased.
But in my opinion TDD is much more than a different way to test a system. I believe that it modifies completely the nature of the testing tasks. Actually, I think that this change is so profound that TDD was able to transform a hated activity in something that programmers can really enjoy.
In the past testing was something boring. Programmers didn’t like to spend much time testing their code; they preferred to delegate this task to the QA team. And it was considered normal if the testers in the QA team did find some bugs. After all, the software developers were too busy coding; they did not have time for all the repetitive actions related to testing. Most programmers felt that testing was an activity that did not require from them much creativity, neither used their special skills.
This reaction of programmers in relation to testing can be explained by concepts of Positive Psychology. According to the Flow theory, a person can only enjoy a task if there is a match between his abilities and the complexity of the task. As depicted in the graph on the right, when the person is skilled but the challenge is low the activity is considered boring. In contrast, when the person is skilled and the challenge is high, this can bring him to a state of arousal. In traditional testing methodologies there was a mismatch between the ability of software developers and the complexity of the testing task. The consequence is that programmers could not enjoy testing.
But TDD changes this picture because it transforms testing in just another type of programming task. When the software developers implement automated tests, they are actually writing code. Therefore, there is a match between their skills and the complexity of the testing task. Suddenly, testing becomes something that programmers can really enjoy doing.
This match between skills and complexity is in the root of any successful game. And TDD actually has some other characteristics that make it similar to games. This reminds me the concept of Gamification:
“Gamification is the use of game design techniques and mechanics to solve problems and engage audiences. Typically gamification applies to non-game applications and processes, in order to encourage people to adopt them. Gamification works by making technology more engaging, by encouraging users to engage in desired behaviors, by showing a path to mastery and autonomy, and by taking advantage of humans’ psychological predisposition to engage in gaming. The technique can encourage people to perform chores that they ordinarily consider boring.”
In TDD, using a framework such as xUnit makes the progress clearly measurable, like earning points. You start with a set of tests that are all “red” and gradually make them become “green”. It’s like a game: When all your tests are green, you win and this level of the game is over. Then you can move to a more advanced level, augmenting your challenge, either by adding new, more complex tests, or by performing some refactoring in the code that can potentially break some of the existing tests.
According to the book Gamification by Design: Implementing Game Mechanics in Web and Mobile Apps, another very important characteristic of games is their immediate feedback:
“One of the most straightforward and important game mechanics, and one that is increasingly a cornerstone of the gamification movement, is feedback. Broadly defined, feedback is returning information to players and informing them of where they are at the present time, ideally against a continuum of progress.”
Every time you modify the code, you are actually taking the risk of breaking some tests. This generates the suspense of executing the tests after you made several changes in the code, to check the tests are still working. In practice, code refactoring can become an activity full of adrenaline. But the immediate feedback provided by automated tests allows you to take corrective actions in the case there were failures. At this stage, the coding-testing process can progress in fast iterations.
Sometimes you need to modify the tests because some requirement has changed. Of course in this case the right thing to do is to first change the tests and then the code. But I know that some programmers do exactly the opposite, and they first change the code and then check what tests were broken. This may be easier, because sometimes it is difficult to identify all the tests that are related to some specific requirement. Changing the code first is surely not the right thing to do, but it can be more fun.
If you still have any doubt that TDD is like a game, take a look in the TDGotchi application. I think it is a very original idea (but I must also say that I did not install it myself to check if it works).
So go on and have fun testing. It’s possible!
Interesting article and amalgamation of psychology, software, and gaming. Enjoyed reading.
Thanks, Fridy! I’m already writing an additional post about the Behavioral Economics of Agile.
Was also discussed lately @coding horror
Thanks! It’s an interesting article.
As a “lone wolf” developer, I’ve been using TDD since before it had a name. When I plan to add a new feature to our flagship product, a “concept” test is part of the design process. I find that a real-world illustration of the feature, in the form of a test, actually helps me design the feature. So by the time I start coding, the test already exists, and is, in fact, part of the feature’s documentation, as well as a guide to the implementation. (Of course, the test should be kept independent of the implementation, reflecting only the functional requirements for the feature.)
I find that TDD offers a couple of benefits not usually discussed. The tests it produces serve two additional functions for us — marketing and training. The test become part of the regression test bed for the product, but they often also go on our Web site as examples of the features involved, and those same examples are used to help train customers on the feature as well. Yet another benefit is the pleasure and gratification that comes from watching my implementation do the job I designed it to do, when the test succeeds.
One thing that needs to be added to the “Flow” diagram in the article you cited is another dimension — self-confidence. Unfortunately, in the real world there are anomalies between skill and self-confidence in both directions — people whose high self-confidence is not justified by their skill level, and people whose skill level is not reflected by their low self-confidence. The former create disasters; the latter are usually underemployed and frustrated.
Very interesting post, and you surly on to something! I totally agree from my own experience that the feeling is “game” like, the constant feedback about the progress(by passing tests) and the “Victory” when the feature is done with no/little logical bugs makes it so addictive.
I enjoyed reading it!
Thanks, Tzachi! I’m glad you enjoyed my article. I’m now working on a related post about the Behavioral Economics of Agile development.
In any software, TDD gets very interesting when one clubs it with the Code Coverage. Otherwise, the intent of TDD gets no where. By TDD, if the code is still not covered, it’s the same quality which still raises number of defects in the QA. So I believe, If TDD is combined with Code coverage, its awesome.
In any software, TDD gets very ientresting when one clubs it with the Code Coverage. Otherwise, the intent of TDD gets no where. By TDD, if the code is still not covered, it’s the same quality which still raises number of defects in the QA. So I believe, If TDD is combined with Code coverage, its awesome.
Pingback: “My Code is Exceptional, I Don’t Need TDD” | James Grenning’s Blog
Excellent thoughts. Since we spend most of our waking hours at work, any tools and techniques that make work more enjoyable will increase our overall well-being. Most agile practices are good at this as I wrote in my post at http://www.leadingagility.com/the-psychology-behind-agile-success/
Pingback: Rétrospective 2012 | Agilité, Architecture, C++ "in the mix"Agilité, Architecture, C++ "in the mix"
Pingback: On Technical Debt and the Psychology of Risk Taking | Effective Software Design
Pingback: 35 Agile Development Best Practices | Effective Software Design
Pingback: Attention Agile Programmers: Project Management is not Software Engineering | Effective Software Design
The same problem with TDD is like with Agile, Extreme programming practice and many others development practice and schools is the balance. How much and how far to take it? TDD will definitely raise the quality of the product but the cost as well.
So before we build an automated, sophisticated and expensive test we have to think about ROI (return on investment).
I think that in the case of TDD you must adopt it completely. Partial tests may give you a false impression about the correctness of the system.
In my opinion the problem with TDD is when the design is not stable, what requires the tests to be changed whenever the code is changed. This is the reason I do not believe in Emergent Design.
My point is too much TDD is the same as too much Agile practice. An effective software design and development should include an effective TDD approach. The TDD should be a means not a goal.
In an agreement or not I enjoy reading your articles!
Sure I agree with you that TDD should be a means and not a goal, and it’s certainly possible to exaggerate doing too much TDD. Thanks for your comments, Zoran, I appreciate the feedback!
Pingback: The End of Agile: Death by Over-Simplification | Effective Software Design
Pingback: Lean Software Development: Before and After the Last Responsible Moment | Effective Software Design
Pingback: Antifragile Software Design: Abstraction and the Barbell Strategy | Effective Software Design
Pingback: Re-Post: The End of Agile: Death by Over-Simplification | Youry's Blog
Pingback: The Psychology of Agile Software Development | Effective Software Design
Pingback: Developing Cross Platform Application using Qt, PyQt and PySide : Test Driven Development and Unit Testing – Part 3 of 5 – Phytonthusiast
Pingback: Developing Cross Platform Application using Qt, PyQt and PySide : Test Driven Development and Unit Testing – Part 3 of 5 – Nim4 Karimi
Pingback: TDD and the Gamification of Testing - My Blog