K. Sabbak

Code Princess

On Mistakes in Programming Books

December 07, 2017

Today I was reading Test Driven Development: By Example, by Kent Beck and following along with the python example. I had hit a few snags when copying directly from the book, but nothing I wasn't able to fix in about 30 seconds, but then I ran into a huge problem and it took me the better part of an afternoon to sort through.

At first I was very upset about it.

After all, I was trying to learn TDD from Kent Beck by example and his example was not working. Now instead of spending my time learning TDD, I was spending time debugging something that the book insisted was fine. "Why is it doing that? It shouldn't be doing that!" and, according to the book, I was right, it shouldn't be doing that. But my computer didn't have my book, my computer only had my code, and Python isn't about to be wrong about Python.

A couple hours, some rubber ducking and an epiphany later, I realized what was happening. This explanation will make a lot more sense if you have the book, but I'll try to provide enough context. On page 113, there's the following excerpt:

We can't leave xUnit without visiting TestSuite. The end of our file, where we invoke all of the tests, is looking pretty ratty:

print TestCaseTest("testTemplateMethod").run().summary()
print TestCaseTest("testResult").run().summary()
print TestCaseTest("testFailedResultFormatting").run().summary()
print TestCaseTest("testFailedResult").run().summary()

Except the end of my file had several lines that were formatted like TestCaseTest("testTemplateMethod").run(), no print, no calling summary - and I hadn't seen anywhere else that would indicate that I should have added those parts. So I panicked and added the missing parts that I knew the book was about to tell me to change. And I started seeing results that I didn't expect. The summary was printing "1 run, 0 failed" every time, even when the assertions inside the test were passing and expecting something like "1 run, 1 failed". I could not figure out what was going on, and that's when I started debugging. Ends up, run was being called twice overall, and instantiating two different TestResult objects, one that had the one that passed the assertion inside the test and one that printed the "1 run, 0 failed" I had been so confused by.

I can't say for sure if this was an actual mistake on the part of the publisher, including the print and summary without the context. After all, if I had a better grasp of what I had been copying, I probably would have been able to figure it out much faster. But it was certainly an oddity. And only by running into this oddity and spending time "solving" it, did I fully understand what I had been faithfully copying. I thought I had understood, but it was clear once I finished working through the unexpected results that I hadn't fully grasped it before.

A quick search hasn't come up with any newer editions of this book, and I'm actually rather glad. After all, the few legitimate mistakes and typos I found (e.g. a way of writing an assertion that would never return false), I was able to overcome with the help of my existing understanding and a bit of help from the error messages. Because I had full understanding of the context, they caused me virtually no problems. And honestly, historically, when I've faithfully followed a book, I've learned a lot, but my learning went deeper and stuck better when I was solving a problem whose answer wasn't on the next page.

Maybe this is just me justifying my typos, excusing a lax editor, or giving myself permission for lazy reading comprehension, but ultimately all three of those things end up leading to a deeper understanding of what I'm working on or something adjacent to it.

Tags: learning