“Don’t obey the Testing Goat!” — When Test-Driven-Development isn’t the Answer

TDD has revolutionized the game of Software Development. But no process is flawless for all given situations…

Diptonil Roy
7 min readApr 15, 2022
Max: “assertFalse? Should it not be assertTrue?”. Alex: “With assertTrue the test went red”.
Cartoon by Geek and Poke

I remember the time from my initial years of programming when I came across the concept of Test-Driven Development and, like most novice opinionated developers, discarded the idea downright — comically stating that the concept is the embodiment of redundancy and doltishness (excuse me— I hate myself enough for this anyway). It felt like repeating the obvious and mundane by checking a piece of code against an outcome that was guaranteed to be true. In case it was not, the only conclusion that my immature self would come across was the fact that the programmer was inept at their job.

Fortunately things changed as I started reading more books on the subject and most importantly, started making projects with a broader scope. I slowly started to grasp the essence of the discipline, as with most other developers who initially view this methodology with contempt. I realized that TDD is not meant to be understood by absolute beginners. It is something that can only be understood by those who have suffered for not adopting it. Experience (painful ones), and not books, is the best source to know why it is necessary. Newbies with little to no clue as to how the HTTP request gets processed by the server or how the database model API of their chosen framework functions would only get irritated further at their incompetence rather than accept the methodology as a rational discipline (which, for their stage, is rather natural). And anyway, how can a developer truly appreciate the benefits of TDD when they’re practicing smaller projects such as todo-lists or library-websites?

What exactly is TDD, though? My Blog just works fine without even using any fancy approaches…

Test-Driven Development is an approach for developing software (which sort of derives from Agile Development Practices) in which the phases of Development and Development Testing in the Software Development Life-Cycle becomes interweaved. Testing is not as much an independent stage as Requirements Specification or Software Maintenance, although it is mostly dependent on the team developing the project (most companies keep User Testing and Release Testing as a necessary Design Principle that is to be carried out at a later stage compulsorily).

Procedurally, tests are written before the code of the actual application is. It follows the tenets of Red-Refactor-Green; we write a test for a non-existent functionality that fails, we program the functionality (exactly the one being tested, nothing more), we run the test again and check if it works. If yes, we move on to write more tests and build our application block-by-block by following this same iterative process. If not, we sit down, consume as many cups of coffee as needed and do not move on to anything else unless the test passes.

Hierarchy of Test-Driven Development
Development Testing

Coming to the topic of your blog, try adding third-party authentications, extending the application to situations when parts of the system start to depend on other parts, play around with multiple inheritance, deep class hierarchies, model optimizations. Soon enough you’ll find yourself think twice before making changes to your code because you’ll be scared of breaking the logic somewhere. Bugs will inevitably creep in. And for every bug cleared, there will come ten more. This would give rise to some substandard ugly code that skims over your intentions without actually implementing them. You’ll also find yourself letting go of the multiple functionalities that you had planned for the project.

Sounds like dotting all my would-be-dotted ‘I’s and wasting a lot of time…

Harry Percival in his book Test-Driven Development in Python asserts that no matter how silly a test might be, it should be written as long as it checks out all the criteria of testing (test individual atomic functionalities that are to be included by a modular approach and leave out testing functionalities that are already shipped by the language or framework being used). “Follow the testing goat!”. This pedagogy actually seems somewhat agreeable in delivering the importance of testing to beginners as well (although it does force the ritual of TDD on the readers, which is honestly the best a book on this subject can accomplish).

Fine, then. I’m sold. It’s an approach worth trying at least…

I had adopted to the discipline of TDD rigorously, which resulted in a burst of confidence in me. But soon I started running into certain pitfalls (the chain of events started with a hackathon, I remember) when I started to debate the utilities of the technique. No doubt it was extremely powerful, but I had to come to a conclusion that it doesn’t suit all forms of software development. Here are a list of cons that I have personally come across:

  1. TDD is not suitable for groups having heterogenous notions about the process: Obviously, if you’re the only one among the team of programmers well-versed with this discipline, there is not much benefit of streamlining your operation with writing tests. Others not in favor of TDD would normally expect you to hand over your segment as soon as possible, with no regard to any tests written. They would not be expected to concern themselves with tests. You would want to stick to the group workflow and avoid conflicts rather than going about your own.
  2. TDD at hackathons may slow you down more than you would expect: TDD gets a lot of flak for slowing down development (which is a controversial opinion). If closely looked at, it is just borrowing time from the Testing phase of the SDLC. But hackathons (there are a few exceptions to this, but generally) are not really the place where you follow the SDLC by the book. It’s a place of constant toil and sleep deprivation. Bugs are an implied consequence. Care should only be taken as to not let those spill over during demonstration. The main functionality should work. Speaking from experience, TDD slows you down during hackathons considerably. Don’t even think of doing it.
  3. The Tester’s Block: There is no ground rule for building up tests except the fact that each test must cover a single module (unit tests). There are times when creating tests may not be as intuitive as creating its use case. Being stuck creating the tests and thinking if you should or should not test a certain aspect of your code is the Tester’s Block. It’s a big obstruction in case of rapid development and in such cases, it might just be worth it if you stay away from it for the time being and get back to it later.
  4. Repetitive Projects: If you’re out there making repetitive projects in a short span of time — projects that you’ve already worked on in the past with a fair idea of how to implement things (probably because you’re doing a college project or freelancing), my advice would be to skip on TDD (I’ve personally done this and the results have been far better than I’d expected). The goal for is always to save time and do more.
  5. Shifting Gears in between a predefined development process: TDD is a discipline that works only if properly implemented right from the beginning. It makes no sense to try to fit it in your project after covering up the core parts of your application. Not only does it disturb the workflow of the project that you have accustomed do but also different members of the team would pick it up at a different pace. This would only cause delays and resentment.
  6. Projects Lacking a Clear Requirements and Design Plan: You are unsure about what exactly your project is going to be about. There are no proper design plans drawn up for it. Everything is still in the phase of ideation but you need to start development right away because of a deadline. Despite the unprofessionalism, such cases do exist at large. Stay away from TDD in this case. This might as well be the most important point because people do this all the time and then yell about how bad this technique is. If you do not have a clear sense of what exactly you would make and are planning to freestyle it as you go ahead, TDD will slow you down by making you constantly refactor your tests as and when you add or remove certain features. This renders many suites of tests unused and is a huge waste of time. An important part of Testing is that all Requirements should be testable. But if you do not have any predefined set of requirements, what would you test?

So… to do or not to do? That’s the question…

It is worth noting that every person or organization has their own standardized procedure of operations. What may work for one developer and project may not work for the other. The debate over the utility of Test-Driven Development has of late sided towards its adoption as most organizations like being as particular about correctness as possible. It must also be understood that as rigorous the practice may be, TDD is what you yourself make of the discipline. The form of test suites that you make, the conventions used and the test framework chosen — you are at your own liberty to decide these. This synthesis of autonomy with guidelines is what, in my opinion, makes this concept so beautiful.

--

--

Diptonil Roy
0 Followers

I went to the Stock Market today. Did a business.