How granular should you do Red-Green-Refactor?

I just finished Step 3 of the Test-Driven Rails trail.

It feels like we are taking very small steps to making sure each line in the spec passes or doesn’t return an error. Here’s how the video goes about the start of getting it green:

  1. Write the test, where a user can successfully create a todo
  2. The test fails, because no link is on the index, so we add it.
  3. The test fails again because the route new_todo_path doesn’t exist, so we add it.
  4. But now we need to add the new controller action.
  5. And touch new.html.erb.
  6. And generate a Todo model, so we can create a form on the new view.

After each of those steps, rspec was ran. But is that level of detail typical in practice? I feel like we could go on and create everything needed for a new action/view, and test from there… To then see a failure that we need a model Todo for Todo.new.

When I worked through the second half of the video (getting the spec green after click_on "Submit"), I forced myself to only write one or two lines of code, until I get another error message. I added the create route, then redirect_to, then the @todos.each line in the index, and so on… But if I were writing this app like I normally do, I would do everything related to the create action, and displaying the info in one go, then calling rspec.

It probably does feel like overkill, but I would encourage sticking with this approach, running the test even after a tiny change, to help build the habit. When you move onto more complex code, there will be more chance of making a something going wrong, so running the test will catch that early so you don’t need to backpedal. TDD is often about exploring unknowns – the path is rarely as obvious as it is here.

Running the test shouldn’t feel like a chore. Look into how to configure your editor so that you can trigger it with a single keypress (in Vim I use -t to run the test under the cursor, or -l to re-run the last test).

The other thing which might discourage you from running the tests is if they’re slow. Using Spring can help, but a better approach is to try decouple your code from Rails so they take milliseconds to run. This a more advanced topic, but Gary Bernhard’s Destroy All Software series covers it in detail.