Rails scaffolding and TDD are incompatible (but that’s okay)

by Jason Swett,

Testing + TDD = a serious learning curve

Learning Rails testing is pretty hard. There are a lot of principles and tools to learn. Getting comfortable with testing in Rails (or any framework) often takes developers years.

Compounding the difficulty is TDD. If I’m just starting out with testing, should I learn TDD? Writing tests at all is hard enough. How am I supposed to write a test first?

And if the “testing + TDD” combo doesn’t generate enough cognitive turmoil, “testing + TDD + scaffolding” makes the scenario even murkier.

Scaffolding and TDD

In my experience most Rails developers take advantage of scaffolding to generate CRUD interfaces really quickly. Scaffolding is of course awesome and a big part of what makes Rails Rails.

Where things can get confusing is when you mix the ideas of “I want to use scaffolding to build an application quickly” and “I want to TDD my Rails app”. You cannot do both at the same time.

It seems obvious to me now but it took me a long time to realize it. In TDD, I write the tests before writing code. Scaffolding generates code but not tests*, the exact opposite. So I can’t apply TDD to scaffold-generated code. Test-after is my only option.

*It’s true that an application can be configured to automatically generate the shells of tests whenever a scaffold is generated, but they’re just shells of tests and they don’t actually test anything.

What to do about this TDD-scaffolding incompatibility

So, scaffolding and TDD are incompatible. What do we do about this?

My answer is nothing. The fact that scaffold-generated code can’t be TDD’d isn’t a bad thing, it’s just a fact. I’m making a conscious trade-off: in exchange for getting a bunch of CRUD code for free, I’m trading away the benefits of TDD in that particular area. I think on balance I come out ahead.

This fact does mean that I have to exercise a little more discipline when I’m working with scaffold-generated code. TDD automatically results in good code coverage because, if I follow the methodology to the letter (which BTW I don’t always), I never write a line of code without writing a test first. The rhythm of the red-green-refactor loop means that I don’t really have to apply much discipline. I just put one foot in front of the other according to the rules of TDD and when the dust settles I have good test coverage.

But when doing test-after, I need to resist the temptation to say “Hey, this code works. Do I really need to write a test? I’ll just move onto the next thing.”

How I write tests for scaffold-generated code

After I generate a scaffold I’ll usually follow something like the following process.

  1. Write model specs for attribute validation
  2. Write a feature spec for the “happy path” of creating the resource
  3. Write a feature spec for the “happy path” of updating the resource
  4. Look for anything that would be tedious to regression-test manually and write a feature spec for that

That’s about all I worry about for scaffold-generated code. If during the course of development a stupid bug pops up that a test would easily have prevented, I’ll backfill that code path with a test. And if I need to extend the functionality provided by the scaffold (in other words, if I need to write new code manually), I’ll TDD that, because at that point there’s nothing stopping me from doing so.

6 thoughts on “Rails scaffolding and TDD are incompatible (but that’s okay)

  1. drew

    If you’re writing tests for scaffolding-created code either:
    1) the scaffolding creator should also create tests for you or
    2) in some way the scaffolding is already tested and YAGNI.
    Probably #2. If neither, then please contribute scaffold tests so that everybody is in situation #2!

    Writing those tests makes people look busy and drives coverage numbers up. The activity might please clueless managers who don’t know what to measure. Those can exist. An explanation of how managers should actually measure work value is beyond the scope of a comment but would make a welcome blog post.

    Reply
  2. Jason Swett Post author

    I mostly agree. For #1, it would be nice if the scaffold generator were to also generate tests for you, but it doesn’t. So until someone writes a fancy tool that generates those tests, those tests for better or worse need to be written manually.

    Reply
  3. rsmokeUM

    I like how you reinforce that even though scaffolding is full of goodness, especially for the newer to Rails folks (aka. moi), you want to resist the temptation to skip tests and move on. I have found that when I move on and think, “Looky me, I am more efficient”, I pay for this short sightedness in the long run, ALWAYS!

    P.S. Your blog and podcast and courses are really answering a lot of questions I have had about TDD in general. I can’t thank you enough for what you provide to the community as a resource!!!

    Reply
  4. Paul

    Good point they are sort of anti-TDDish.

    I feel like the scaffold generators in Rails are for the most part best suited for learning Rails, and for marketing it. Selling the simplicity.. They’re great for showing you how a controller should look, but I rarely actually use them in practice any more, they don’t save a lot of time unless you’re working on bootstrapping a new application, and are creating a whole bunch of new controllers and routes in a short period of time. On an established application that’s rarely the case.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *