As a developer, when you hear someone use the acronym TDD, do you think:
- Yup, I’ve heard of that. Is it good?
- Hmmm, how is TDD related to software development? Isn’t it part of TTY/TDD. (Telecommunications Device for the Deaf)
- I tried that once, really slowed down my dev time. In fact, I missed a deadline because of TDD.
While each of the reasons above may be valid, as a developer, you should say:
“YES!! I embrace the concept of Test Driven Development!!”
Let’s talk about TDD in real world use. Since I have been introduced to TDD, I can only admit to one relatively simple project where I employed TDD in its true, defined form. I had the luxury of creating an app from scratch, so I didn’t worry about an existing code base.
When I used TDD as defined, I wrote my tests, ran the tests (they of course failed), wrote the actual code, ran the test and the test failed. Eventually, I was able get the test to succeed. Sometimes, I modified the test, sometimes I modified the code. But in the end, I had complete test coverage of a function or a class method.
As any developer can attest, it is not common where one starts a project from scratch. More often, the developer inherits a code base and is told, “We need this app to change so it prints Pi out to 40 places whenever you click the Pi button.” (Fortunately, this is only an example. When I was given this assignment, I only had to print 15 places beyond the decimal point. HAH!)
What I have been doing for a number of years is really a hybrid approach to TDD. That is, concurrently, I write the test code and the actual code. This could be called Test & Code Driven Development (T&CDD). But when the code is completed, I have close to 100% code coverage. This gives me a large degree of confidence when the code is deployed. In addition, I know if I modify code, then run the tests and the test fails, that means I have work to do. I evaluate whether the test procedure needs to be modified, or if the code is wrong. I always think long and hard before I change the test code. I evaluate whether the requirements have changed, if I added a feature that should be in its own container, or if I really introduced a bug.
While I know my T&CDD approach is not the standard approach, this is the approach many developers have adopted.
Getting specific about the way I write unit tests, I follow the AAA paradigm. The AAA paradigm stands for Arrange, Act, Assert. Arrange is the test setup, Act will execute the code to be tested, and Assert checks the result. Every unit test has these three comments breaking up each unit test. This makes the unit test code easier to read, and I know I have to perform the “things” when writing a unit test.
One nice thing about unit testing is that it’s not specific to any language. I have test code in Visual Studio in C#, eclipse Java using junit, PHP with phpunit, and of course Python using unittest and in django using TestCase.
As powerful as unit testing is, you should not rely 100% on a successful unit test run and smugly say “My code is perfect!” What about the case where you have a web app and pressing a link doesn’t send you to the correct page? Your unit tests all passed, but your app is broken.
One needs to include testing for module to module or API testing using tools like Postman, and end user testing using a product like Selenium. A properly written Selenium test would have found the broken link bug.
As professional software developers, we take pride in our work. Having a complete test suite that includes TDD (or T&CDD) along with module to module and Selenium tests allows one to sleep confidently at night, knowing the call from Level 2 tech support is extremely unlikely. And you won’t hear someone disparage your work, because you know it works!
“Once in a while you get shown the light
In the strangest of places if you look at it right”
– Garcia & Hunter