(I’m in Chicago for RailsConf this week. If you see me around, say hi! I’d love to meet you. I’m the older one in the picture in the sidebar.)
A reader asked a great question about testing in a comment on one of my articles:
I know I also need to get the “TDD flywheel” moving, but TDD is very unfamiliar to me. Do you have any recommendations on how best to begin with RSpec or is it just a “get in there and hack away” kind of thing?
So I answered it:
If you’re not settled on one or the other, you might actually find minitest to be easier to get started with. It’s a little more ‘methods and classes’, so you can focus completely on learning and practicing TDD without also having to learn a new syntax.
Rails has a pretty good guide on test terminology, assertions, and how to get tests running in general in Rails.
The best way to learn TDD is to practice. These are the steps you should follow:
- Write a test that assumes that the code you need is already there.
- Run the tests, make sure your new test fails
- Write the simplest bit of code that will pass the test. Don’t overly abstract or refactor here.
- Run the tests, make sure your new test passes
- Refactor your code to remove duplication (or make the code more expressive).
- Run the tests again (to make sure they still pass).
- Return to step 1.
While you’re practicing TDD, you should keep asking yourself: Which step am I on? Did I skip a step? Which step is next? (You should always be in one of these steps.) This will help keep you on the right track, which is really important while you’re learning something new. “Practice makes permanent”, so you don’t want to practice the wrong thing!
But also, give yourself permission to mess up. You’re learning, it’s totally OK! It’ll get a lot easier as you do it more often.
Eric Steele, who’s also writing a book about testing, brought up a key point that I missed:
The part of TDD that gets left behind is the amount of planning that happens before step 1.
Tests are where the requirements of the app meet your planned implementation. Test driven development has a hard dependency on knowing what the app should do, and assumes that you have an idea of how to do it.
When we first start building with Rails, we don’t know a lot. We spend a lot of time writing experimental code until we get a result similar to what we’re looking for. You do this less and less as you learn more. I think this is why TDD starts with ‘write a test’ and not ‘figure out what you’re building’. By the time you’re testing, you have plenty of experience under your belt.
I’d add these steps before ‘Write a test’:
- Brainstorm, justify, and cull requirements. Avoid coding at all costs.
- Plan and design your code that will meet those requirements.
- Tinker with code to answer any unknown questions, but set that code aside.
- Focus on planning more than syntax
- Minimize your tools (I found minitest/fixtures to be really helpful)
- Practice, practice, practice.
Just like anything, getting started with TDD takes practice and the ability to self-correct (or having someone around to correct you). If you can follow a few semi-rigid steps, and stay mindful about where you are in the process, TDD will soon feel totally natural to you.