Real World TDD


This is perhaps the most difficult section to write because of the number of people who participated directly or indirectly in this book.

I will start by thanking my father, mother, and brother, who supported me all the time on the decision to get a master's degree, understanding how science should be done, and who suffered with me in the times of great stress (which happens during all master's!).

I also thank my master's and doctorate advisor, Professor Dr. Marco Aurelio Gerosa, who taught me how things work over there. Without him, I think this book would be very different; it would be more passionate, but less true. If my text focuses on TDD in an unbiased and impartial way, he is the one to blame.

Paulo Silveira and Adriano Almeida also deserve a reminder. Even when "Casa do Código" did not in fact exist, they had already accepted the idea of the book on TDD. Thanks for the confidence.

All people from the previous companies at which I worked also helped me with the countless hallway conversations about the subject. This certainly greatly enriched the text.

Thanks also to friends José Donizetti, Guilherme Moreira, and Rafael Ferreira, who spent time reading the book and giving me suggestions on how to improve.

Finally, thanks to you, the reader of this book. I hope it helps.

Who am I?

My name is Maurício Aniche, and I have worked in software development for about 11 years. In most of these 11 years, I worked as a consultant for different companies in the Brazilian and international markets. Surely, the languages I used most throughout my career were Java, C#, and C.

As I always jumped from project to project (and, therefore, from technology to technology), I never went too deeply into any of them. On the contrary, I always focused on understanding principles that could be taken from one technology to another, so that in the end the code would have quality, independently from the technology used.

In my final year of school before graduation, in 2007, I started reading more about the idea of automated testing and Test-driven Development (TDD). I found the idea very interesting, and I believed it to be useful to write a program to test your program, and I decided to practice TDD on my own to better understand how it worked.

I really liked what I found. From 2007 onwards, I decided to practice, research, and better disseminate my ideas on the subject. I started slowly, just blogging what was on my mind, sharing that I would appreciate some feedback from other developers. But in order to make a more decent approach, I decided to enter the master's program at the University of São Paulo. There, I researched the effects of practicing TDD in design classes.

At that time, I attended most of the events related to the subject. I lectured in the main events of agile methods in the country (Agile Brazil, Agile Meeting), software development (QCON SP and DNAD), among other smaller ones. I also participated in international events; I was the only Brazilian speaker in the First International Workshop on TDD in 2010, in the city of Paris. I have also participated in academic events. In 2011, I presented a study on TDD at the WBMA (Brazilian Workshop on Agile Methods) and, in 2012, at the largest Brazilian symposium on software engineering, the SBES.

Currently, I work for Caelum as a consultant and trainer. I am also a PhD student at the University of São Paulo, where I continue research about the relation of unit testing and code quality.

Therefore, this is my relationship with TDD. In recent years, I have looked at it from all possible points of view: practitioner, academic, researcher, passionate, cold. This book is an account of everything I have learned in these years.  


TDD is one of the practices of software development suggested by various agile methodologies, such as XP. The idea is to make the developer write automated tests steadily throughout the development. However, unlike what we are used to, TDD suggests that the TDD developer should write the test even before implementation.

This simple cycle inversion brings many benefits to the project. Test batteries tend to be larger, covering more cases and ensuring a higher external quality. Moreover, writing unit tests will force the developer to write code of higher quality because, as we will notice throughout the book, in order to write good unit tests, the developer is obliged to make good use of object orientation.

Practice helps us write better software with better quality, and a better code is more easily maintained and evolved. These two points are very important in any software, and TDD helps us to reach them. Every practice that helps to increase the quality of the software produced should be studied.

In this book, I tried to include the whole experience and everything I have learned over these past years practicing and researching on the subject. I also showed the other side of the practice, its effects on the design of classes, which is widely spoken about but rarely discussed and explained. The practice of TDD, when correctly used, can be quite productive. However, as you will see throughout the book, practitioners should always be alert to the clues that the test will provide about our code. Here, we will go through them, and at the end of the book, the reader will have at hand a great new development tool.


For whom is this book intented?


This book is intended for developers who want to learn to write tests efficiently and who want to learn how to further improve the code they produce. In this book, we use Java to demonstrate the concepts discussed, but you can easily transfer the discussions made here to your favorite programming language. Even if you already practice TDD, I am sure that here you will find interesting discussions on how the practice provides feedback about problems of coupling and cohesion, as well as techniques for writing better tests that are easier to maintain.

Testers can also benefit from this book, understanding how to write test code with quality, whether using TDD or not, and how to report code problems for the developers.


How should I study?


Throughout this book, we work on several examples, very similar to the real world. Every chapter has a practical part and a theoretical part. In the practical part, much test code is written. In the theoretical part, we reflect on the code produced up to that time, what was done well, what was badly done, and we improve it accordingly.

The reader can remake all codes produced in the chapters. Practicing TDD is essential for the ideas to become natural. Furthermore, Caelum also provides an online course of automated testing *, which can be used as a supplement for this book.

Enjoy your reading!


  • 1 - Introduction
    • 1.1 - Once upon a time there was an untested project...
    • 1.2 - Why should we test?
    • 1.3 - Why don't we test?
    • 1.4 - Automated tests and TDD
    • 1.5 - Conclusion
  • 2 - Unit tests
    • 2.1 - What is a unit test?
    • 2.2 - Do I really have to write them?
    • 2.3 - The First Unit Test
    • 2.4 - Continuing to test
    • 2.5 - Conclusion
  • 3 - Test-Driven Development
    • 3.1 - The problem of Roman numerals
    • 3.2 - The first test
    • 3.3 - Reflecting on the subject
    • 3.4 - What are the advantages?
    • 3.5 - A little of the history of TDD
    • 3.6 - Conclusion
  • 4 - Simplicity and Baby Steps
    • 4.1 - The Salary Calculation Problem
    • 4.2 - Implementation in the simplest possible way
    • 4.3 - Baby Steps
    • 4.4 - Using baby steps in a conscious way
    • 4.5 - Conclusion
  • 5 - TDD and Class Design
    • 5.1 - The Shopping Cart Problem
    • 5.2 - Tests that influence in class design
    • 5.3 - Differences between TDD and tests in the traditional way
    • 5.4 - Tests as drafts
    • 5.5 - Conclusion
  • 6 - Quality in Test Code
    • 6.1 - Code repetition between tests
    • 6.2 - Tests nomenclature
    • 6.3 - Test Data Builders
    • 6.4 - Repeated Tests
    • 6.5 - Writing good assertions
    • 6.6 - Testing lists
    • 6.7 - Separating the Test Classes
    • 6.8 - Conclusion
  • 7 - TDD and Cohesion
    • 7.1 - Again the Salary Calculation Problem
    • 7.2 - Listening to the feedback of tests
    • 7.3 - Tests in private methods?
    • 7.4 - Solving the Problem of the Salary Calculator
    • 7.5 - What to look for in the test related to cohesion?
    • 7.6 - Conclusion
  • 8 - TDD and Coupling
    • 8.1 - The Invoice Problem
    • 8.2 - Mock Objects
    • 8.3 - Explicit dependencies
    • 8.4 - Listening to the feedback of tests
    • 8.5 - Stable classes
    • 8.6 - Solving the Invoice Problem
    • 8.7 - Testing static methods
    • 8.8 - TDD and the continuing creation of interfaces
    • 8.9 - What to look for in the test in relation to coupling?
    • 8.10 - Conclusion
  • 9 - TDD and Encapsulation
    • 9.1 - The Problem of The Slips Processor
    • 9.2 - Listening to the tests feedback
    • 9.3 - Tell, Don't Ask, and Demeter's Law
    • 9.4 - Solving the Slips Processor Problem
    • 9.5 - What to notice in the test regarding encapsulation?
    • 9.6 - Conclusion
  • 10 - Integration Tests and TDD
    • 10.1 - Unit testing, integration, and system
    • 10.2 - When not to use mocks?
    • 10.3 - Tests in DAOs
    • 10.4 - Should I use TDD in integration tests?
    • 10.5 - Testing Web Applications
    • 10.6 - Conclusion
  • 11 - When not using TDD?
    • 11.1 - When not practicing TDD?
    • 11.2 - 100% code coverage?
    • 11.3 - Should I test simple code?
    • 11.4 - Common mistakes while practicing TDD
    • 11.5 - How to convince your boss about TDD?
    • 11.6 - TDD in Legacy Systems
    • 11.7 - Conclusion
  • 12 - What now?
    • 12.1 - What to read now?
    • 12.2 - Difficulty in learning
    • 12.3 - How to interact with other practitioners?
    • 12.4 - Final Conclusion
  • 13 - Appendix: SOLID Principles
    • 13.1 - Project Symptoms of Classes in Degradation
    • 13.2 - Principles of Class Project
    • 13.3 - Conclusion