In Defense of Sliming
It’s the one and only Slimey Worm from Sesame Street!
When you write a new feature using a Test-Driven Development process you start out with a simple test, often creating an instance and calling a method on it:
If you are strictly following TDD, you’ll try to write the simplest code that could pass the test, so your first code that passes the test might look like this.
The code has no real logic, but it does pass the test, by just returning the expected value as a constant.
This technique, where you return a stopgap value that is not intended to be final just to pass a test, is called sliming. Well, Gary Bernhardt called it sliming in a Destroy All Software episode, and I picked it up. I have no idea where Gary got it.
If you are following some kind of “How to TDD” lesson (like, for example the one in Rails 4 Test Prescriptions), the tutorial may be kind of apologetic at this point. The author will often write something that boils down to “I know this seems silly, but it doesn’t take much time, so, just go ahead, and we’ll get past this and never speak of it again.”
One of the things that happens when you describe TDD in a tutorial is that spelling out each brief test and code session makes the process seem ridiculously long. A sequence that might take a minute to actually do takes much longer to describe, and makes TDD seem really expensive. Being a little deprecating about sliming is part of the handwaving that tries to explain that TDD isn’t that burdensome.
And somewhere in the handwaving and the slightly abashed eagerness to apologize for making the tutorial subject do something that might seem uncomfortable, we (and again, I mean, I) sometimes forget to explain why the sliming step is useful, and why it’s not just some weird tick that we saw Kent Beck do once.
That’s an excuse, I’m done apologizing for it. Sliming is great. It’s an often-essential often-overlooked part of the testing mindset.
There are a few things I like about the slimed test in an example like the above.
- Sliming allows a quick test of the structure of my proposed code separate from the logic of the code.
- Sliming is part of a mindset of encouraging me to find simple solutions that will quickly make my code pass.
- Sliming encourages me not to think of my solution as fixed, and therefore to write code that can easily be changed.
- Sliming encourages me to think about my test cases to find cases that will cover the problem space.
Plus, it’s fun. When you make a test pass with a slimed method, you (and again, especially if you are me) feel like you’ve gotten away with something. Sometimes, in workshops, when I first show a slimed method, people laugh out loud.
Why does sliming work? It encourages one of the biggest advantages of TDD: moving in small steps. Moving in small steps is good because small steps are usually easier than big steps, you often discover that you can solve your feature with less code than you thought.
The classic description of the TDD process goes something like this:
- Write a failing test
- Write the simplest code that makes the test pass (or alternately, clears the current error)
- Refactor
Then repeat, trying to find a new test that will fail.
This is a not a process that suggests that you spend 10 minutes setting up an end to end test, then spend three hours making it work. It’s a process that suggests much smaller, faster, loops. Less than fifteen minutes. If you can, less than a minute.
Which is where sliming comes in. If you look at the slimed method at the top of this post, the temptation is to say that it doesn’t prove anything. That’s not true. The test can fail. It fails if there is no PriceCalculator
class, it fails if the class can’t be initialized with an Item
, it fails if there is no calculate
method. (Sometimes, I’ll run the test in between each of these steps. Small step, quick test, verify you are on track.)
The slimed test verifies the API that I’ve set up. I can verify the API before I need to tests business logic, and I can do so quickly, using very little mental effort.
A lot of the benefit of TDD comes when you allow testing to guide you to solutions rather than imposing the solutions. The way you make this happen is by writing very simple code — what Sandi Metz and Katrina Owen call “Shameless Green” in 99 Bottles of OOP. Once you have the simple solution, you can then try to determine the abstractions needed for changeable code.
The slimed method isn’t forever. As soon as this test passes, I’m off writing the next test, which either has a different item as the argument or possibly has more then one item. Whichever it is, the slimed method is no longer the simplest way to make things pass, so I can start thinking about logic. But I can focus better on the logic, because I am only trying to make one change at a time.
So the next time you are writing tests for a new feature, take a small step and slime away…