Chapter 4 of “Refactoring, Improving the Design of Existing Code by Martin Fowler, titled “Building Tests” provides an introduction to automated testing.
Here’s my perspective on the chapter:
Video Transcription:
Hey, what’s up everybody, it’s Andy from cleanswifter.com and I’m here to talk about the next chapter in Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” You can buy that book in the Amazon Affiliate link in the description for this video. Last week we talked about chapter 3, Bad Smells in Code. In that chapter, Fowler presents some ideas of what to look for in your code to know it’s time to actually refactor it. This week, chapter 4, titled “Building Tests” Fowler actually talks about some techniques for introducing automated tests within your code. If you’ve been following any of my posts on cleanswifter.com, you’ll know I have a huge passion for automated testing of software. I was kind of excited for this chapter. When I finally got around to actually reading it, it fell short of what I was looking for. Fowler clarifies that this book is not about testing. And the reason I interpret he chose to include this chapter is to recognize the value of automated testing, especially in the time of refactoring. He doesn’t even mention test driven development in this chapter. Now, if you remember test driven development, one of the key steps to test driven development, is that final third step, to refactor everything you’ve done. Test driven development. You start off writing a failing test. Then you write the production code to make that test pass. And then you refactor. Now just bringing it back to Fowler’s book, he doesn’t actually talk about anything in detail with regard to test driven development. In fact I think he kind of just puts this chapter in here to recognize that when you go out to use this as a recipe book of refactoring, that you should keep in mind the value that can be adding tests throughout the process.
If you’re not familiar with automated testing, or haven’t been following any of my posts on <cleanswifter.com> is that remember, automated tests’ value is that it is code testing code. You can execute an entire test bed at the click of a button. Where your entire code base is tested in a matter of seconds. You do actually have to go through the effort of writing these tests, and that’s no small effort. Then you can make changes to the rest of your code base without risk of introducing new bugs. Additionally, when you find a bug, whether that’s reported through QA or an end user, you can first write a test to verify that bug, and then go fix the code to make sure the test passes, you can now have the confidence that that bug will never surface again in your code. For me, that’s really the value of adding tests, knowing that when I find a bug, I can write a test that verifies the bug does actually exist, then I can go fix that code, make the bug go away, make sure the test passes, then never again will that bug surface. This is especially relevant to the iOS development community because at a recent presentation I gave to the local CocoaHeads group here in Philly, there continues to be the majority of iOS development community that doesn’t write automated tests for their code. In that meeting we talked about some of the reasons this may be. For an independent or contract developer, that they don’t feel it is worth their time. Or hard to justify to their client, whether that is them for their own product, or someone else paying them for their time), that it is worth the time to write tests. It’s a 1:1 ratio, for every hour you spend writing production code, you’ll need to spend an hour writing test code. I think until you learn the lesson the hard way, and then see the value of automated tests correcting that, you’ll never be able to justify the cost. It’s like a catch-22, because if you never try it you’ll never be able to justify it to yourself. On the otherhand, if you’re going to wait to see the value before you try it, you’re never going to try it. I think one takeaway from this chapter, that even Fowler calls out, is that specifically, go try to write a couple tests. Don’t spend a lot of time writing an entire big test suite for your entire application, worrying about every edge case, and instead focus on just 1 or 2 tests that are going to add value, and I guarantee you that sometime down the road, you will have your butt saved by the fact that you had automated tests. You will write automated tests, and sometime down the road they will fail because some code change you made introduced an unexpected, but tested for bug. You’ll be happy since you caught the bug and not an end user.
Fowler clarifies the difference between unit and functional tests. Again, I have a ton of documentation on <cleanswifter.com> that helps differentiate and define each of these for iOS development. For unit testing, you’ll be using XCTest as provided by Apple. It’s code that tests other code at the smallest level. You’ll write a test method for each path of conditional code in another class. It requires intimate knowledge of the code you’re testing. Consider it white box testing. You can see the code, to know the conditional paths, and know how to test it. This is in contrast to functional testing. Functional testing is where you would call it black box testing. You don’t have intimate knowledge of the code. Instead, all you’re doing is testing the code from the outside in. This means that you are simulating an end user swiping, tapping, and navigating your app. There are a bunch of tools out there to do this. Apple’s provided tool is called Xcode UI Tests and I personally use a different tool, called KIF. It stands for Keep-It-Functional. It’s open source. Some of the benefits I like of KIF are that it is mature, been in the community for years, you can write your tests in either Objective-C or Swift. I haven’t spent enough time with Xcode UI Tests to know it’s pros and cons, but I did use its predecessor, UI Automation which was Javascript driven and a poorly documented API. It’s soured me on Apple’s provided functional testing tools, so that’s why I haven’t gone back yet. I’ll do that soon and write about it on <cleanswifter.com>.
Another important thing to keep in mind when you write your first test, regardless of whether you are doing TDD or not, and in fact if you are just starting out I don’t recommend jumping right into TDD. But one thing to keep in mind when writing your tests is that you want to see that test fail when you expect it to fail. For example, say you are writing a test for a method that adds numbers. You want to first verify that adding 1 and 2, never returns anything other than 3. Otherwise, you won’t have the confidence that when someting actually goes wrong, that test will actually fail. That gives you a baseline assurance that that test is actually providing that quality check you’re looking for. And trust me, I’ve seen plenty of cases where I’ve written a test and not done this, only to find out that it wasn’t actually verifying, what I thought it was verifying.
It was a pretty short chapter, chapter 4 in Martin Fowler’s book, “Refactoring” where he just introduces the concept of tests. If you’re watching this video and haven’t checked out anything I’ve posted on <cleanswifter.com> around automated tests. And if you’re not writing automated tests for your iOS apps, you should definitely go try that out.
Looking ahead, I’m really excited for the rest of this book. Chapter 4 is the end of the preamble before the actual list of refactoring recipes. Going forward, week by week, I’m going to make a screencast of that refactoring, showing it in action with Swift code, and post it on <cleanswifter.com>. It will demonstrate the transformation from smelly code to nice clean code. That will be done in a screencast where you can go back and watch. The first refactoring we’ll try in the book is Extract Method. It’s a really easy one, but also a really effective one. I’m looking forward to showing you that. Check back next week for that. In the meantime, be sure to checkout <cleanswifter.com>.
Happy cleaning.