Bad Dinosaur!

You Should Check This Out

CollegeJobConnect | Better Undergraduate Recruiting

Wednesday, August 24, 2011

Do you test?

Note: this was in response to a question asked on the Dallas.rb group regarding if, how, and why you write tests (or specs, or whatever you want to call them).

Definitely test. It will feel weird / slow at first, but it helps you write much cleaner, more modular code. I initially hated it when I was forcing myself to adopt it, now I feel naked without it. For me, I find testing important for a few reasons:
  • It helps me think through what I want the app to do should do from a stakeholders standpoint.

  • It helps me and anyone else working on my app from a dev standpoint know how my app and its components should behave - specifications should do just that: specify what certain things should do! I try to always ask myself "What should you do, Mr. [Object]" and then write a spec around that.

    For example, take a look at this:
    You can see what I'd expect if you were to write User#full_name. It says: "Show me the full name when available, or its parts, or default to the email address, which is ensured to be present, if all else fails." Perhaps we drew up this specification when determining how we should handle displaying a "Hi, #{current_user.full_name}" in our UI for the different cases our app might encounter. Or perhaps #full_name was the failing part of our acceptance test when we were writing the code that we wish he had (see The RSpec Book for this reference and a very informative read).

  • It's an insurance policy and time saver. Anytime you change your app you can be confident that other areas still behave as expected. My workflow before TDD / BDD was:
    1. implement some new feature
    2. think through all other parts that could be effected
    3. pop open my dev env and manually test each to make sure things were working.
    This was a waste of time and exposed me to my own human error: perhaps I forgot to do a certain thing or whatever. The computer is your friend (and worker), make it do the checking for you. My workflow is now:
    1. implement some new feature
    2. initiate tests
    3. go make a sandwich, return and see what passed what needs fixing.

  • I found writing expressive and clean unit tests much easier than acceptance tests. If you are using Cucumber, check this out: Imperative vs Declarative scenarios in user stories and try to avoid using the pre-packaged web-steps when possible.

Friday, August 12, 2011

Love, S and P

Tuesday, August 9, 2011

DRYing up those controller specs

I recently had a bunch of duplicate code in my controller specs and wanted to share a solution I arrived at that DRYed things up significantly. Feel free to use it and abuse it and if you have recommendations on how to improve it, let me know.

First, the quick requirements and background: all controller methods must explicitly demonstrate that guests do not have access to certain resources and are told, upon any attempt to access them, that they must login in order gain access.

The first pass was to write the tests, get all to pass, then look to consolidate and improve the suites. Here's the first pass:

These specs duplicate an awfully large amount of code. This is an issue because more LoC translate into more maintenance, more potential areas to make mistakes, and more places that need to be updated when things change. (For example, what if we want to flash an alert of "OH NOZ, SIGN IN FIRST PLZ"? I could find and replace, but that should be handled in one place.)

In order to remedy these issues, I added a controller macro that includes #it_should_block_access_to(action, options = {}), which is passed an action (:index, :create, :update), maps each to a default method (:get, :post, :put) if none is specified, and generates the appropriate routing (member vs collections). It also handles format specification, such as :json, or setting any other arbitrary params via the options hash.

Here's the refactored code:

The controller specs are cleaner, a big chunk of code duplication has been removed, and there is a main handler for these tests that does not (in my opinion) add too much complexity into the testing suite.