I was interested in this talk by Phil Nash to see his approach with C++. TDD is an approach that, as it states it is test driven (and Phil clarifies that it is different from test first). Saying that, there is an assumption that you know your OOA/OOD/OOP well, along with your SOLIDs, or template metaprogramming well, and so on. So, you don’t abandon any of these well-known and well-learned principles; you rather apply them to converge fast on the things that you need to pass a test. The assumption is that such test is the most important thing to do: it may realize a use case, implement a user story, add a piece of functionality, and so on.
As Phil explains, TDD starts with a failing test. Perhaps you’ve written your base classes or interfaces or protocol classes or abstract classes, or primary templates, or…the name doesn’t matter. The thing is, you start with a test that will fail and write the minimal amount of code to make that test pass. That will bring you to a refactoring opportunity, then you try again until the test passes, and so on. This portion of the talk takes 10-15 minutes, but I say they’re well spent to get the best grasp of the talk.
On minute 17 Phil addresses a question on how to introduce TDD on legacy code, and he’s right: it’s very hard. The reason, which is easy to visualize, is that you must have designed your classes with testing in mind–say, X-Injection (constructor, property, parameter), easy to stub (fake, etc) by writing to an interface (or if you use templates, then perhaps a primary template with partial and explicit specializations). You get the idea. This process can be painful, depending on how well you broke your dependencies.
Enough said. Now let’s check the meat of the talk. As the author of Catch, Phil conveniently makes us of it in the talk–and conveniently, too, CLion has built-in integration with Catch. While the examples are with Catch, what matters are the principles, the approach on how to write the test, make sure it eventually passes, and how to go about working with your C++ code to make the TDD cycle happen.
One thing you’ll notice is that source code and test code are together. That’s a style that Phil uses, and he explains that you can move the code out–hey, whatever floats your boat; you may decide to first write a minimal portion of your class, class template, or other artifact, and then write the tests by including those minimal files, and see how that goes.
What I liked about this talk is that it shows you how to go about TDD in a simple way–I perused through the Catch2 documentation and the framework is simple to use and seems like a short learning curve. The examples that Phil gives are designed to show how to go from test to working code in short iterations, little by little, poquito a poco. Hey, had to use some Spanish.
At the end of the talk, Phil answers some interesting questions. One that he addresses that is very common has to do with design and testing: do you give up design when you use TDD and the answer is a resounding no. Any approach that uses tests–POUTs or Plain Old Unit Tests (you see, I can also invent my own acronyms) and TDD, have evolving designs. You design little by little and adapt the design according to the results that you’re getting from the tests. Approaches that I’ve used in the past tend to do a full design (you could call it an architectural baseline to make it sound cool) that takes longer to do. None of them are wrong and one may make more sense given your particular circumstances. The point here is that TDD is a tool that does not forego design, it simply starts with a different assumption and builds from there.
The question remains, though, what will happen when Catch reaches version 22. Will it be called Catch-22?