Testing
What is the true value of testing and how should we approach it? In his talk, How to stop hating your tests, Justin Searls provides some observations about testing and distills his many years of experience in the field into some finer talking points. His advice centers around Structure, Isolation, and Feedback. These topics are expounded with subtopics that cover a plethora of tips and tricks to make testing better and more efficient. I highly suggest for anyone who practices TDD to watch this talk and try to apply some of these ideas. However these topics were not what effected me the most.
This week I was tasked with preparing a code kata focusing on the use of TDD. The idea seemed simple at first but as I dove deeper into it I had to ask myself if I really knew what the purpose off TDD actually was. I knew it helped with code safety and accountability but I felt as if I hadn’t been getting a real handle on how to use it properly. Before diving back in to watch this talk again I decided to check out Test Double’s blog(the company that Justin Searls works for). It was here that I found an article that expressed exactly how I was feeling about TDD and it’s benefits. This article is titled “The Failures of “Intro to TDD””. It was reading this blog post that helped the three rules of TDD to finally click in my brain.
Reading this article was like reading through an exact description of my first forays into TDD and the problem areas I encountered when starting out. Justin goes through the misconceptions that a beginner might have and some of his issues surrounding teaching “Classic TDD”. But there was one sentence that made it all come together and produced one of my greater Aha moments: “TDD’s primary benefit is to improve the design of our code”. I was overlooking this crucial detail and focusing too much on the other incidental benefits to the red-green-refactor code cycle. As it turns out I was essentially missing the third and most crucial factor of this cycle, refactoring. I thought that by creating a failing test then making it pass I was doing all that I had to do to write properly tested code. It turns out I was very wrong.
In order to illustrate how I put this to use I would like to present an example of how I applied TDD to my prime factors kata.
THE TESTS
To start off are the tests that I would end up with at the END of my kata. I used the red-green-refactor code cycle for each of my tests individually. I wanted to put them all at the top for code solidarity and to show what tests I ended up with.
FIRST TRY
The first time I tried this TDD style I wasn’t doing it properly and it was ugly. I was biting off chunks of functionality that were too large and never refactoring afterwords. The problems are evident and while it did what I needed it was neither elegant nor developed using TDD which was the goal.
SECOND TRY
This time I managed to stick strictly to TDD and take off much smaller chunks at a time however I was not refactoring between each test. The result is definitely an improvement over the first try but leaves some definite room for improvement.
THIRD TRY
I should say that these three tries happened over the course of about 3 or 4 days and in between I was reading and studying many different videos and writings about TDD. It was only after watching this talk that I was able to stick to TDD, take appropriate sized chunks of functionality, AND refactor everything before moving to the next test. The struggle was there but I think the resulting code is much improved.
I have spent much of this week hating my tests but little did I know it was because I was missing a key component of the TDD process.