Project Ramon

A learning journey from a Ruby noob perspective

Lunch Panoply: An Rspec Model Refactor

lunch_panoply4_header_img

If you’ve been keeping up with my recent posts, you’re aware that I’ve been test-driving my latest AirPair project, lunch_panoply. Today we’ll be going over a refactor of the model_specs.

Drying up Our Specs

The first thing I look for when refactoring is redundancy. For me, its the lowest-hanging fruit out of a basket full of additional approaches to cleaning up code smells.

Below is an illustration of a code sample from the company_spec:

lunch_panoply4_img1

If we take a look at the first line underneath each of our it blocks, its hard to miss all of those identical factory instantiations, lets see how we can eliminate this unnecessary redundancy from this spec_file.

Rspec allows us to use two memoized helper methods let and let! in order to have some benefits in our tests such as lazy-loading factory objects. Here is a link to an insightful StackOverflow post that goes into greater detail. And here is a link to a post that displays a good example.

Finally, this is how let essentially works:

lunch_panoply4_img2

Using the Rspec helper method let, we have reduced our code to the following:

lunch_panoply4_img3

Admittedly, I was hoping for a complete removal of having to call the company object in each spec. But this isn’t a terrible start, a half-step in the right direction is better than being stuck at square one.

Lets look at another code snippet from the same file, continuing our first approach of simply reducing or eliminating duplicate code smells from the file:

lunch_panoply4_img4

Here we’re setting up more than on instance of company in order to store it inside of an array that will represent an instance variable with the same name companies that holds all instances of the class.

Using let again, allows us to remove each of the identical array assignments in the spec file from the example above.

The code now looks a little less redundant in the sense that we only are defining the companies array one time. Here’s a snapshot of this minor improvement:

lunch_panoply4_img5

So now I have two calls to the let helper method, one for the array companies and the other is to create a company factory object to use throughout the entire spec.

I could add additional let methods that would create or build the various company1, company2 and company3 factory objects, but personally, I find leaving them in as-is is not only easier to read, but prevents me from having to scroll up the entire file in order to see which object’s attributes I’d need for a particular spec.

Using Shoulda-Matchers

I remember a previous mentor session with Mark Simoneau about using shoulda-matchers to tidy up some unnecessarily loquacious specs. I like to use these when testing for specs that tests for the presence of attributes we’ve created presence validations for in the model. Lets take a look at a snippet of some of those specs.

lunch_panoply4_img6

and

lunch_panoply4_img7

The first thing I’d like to address is my less than perfect description strings that describe each of the above specs. The it blocks take a string strictly for humans to read in order to make quick sense of what each specific block of coverage is asserting. I think I can do slightly better at making these descriptive sentences easier to read at a glance.

Addressing the second code snippet from the above illustrations, I’ve changed the text to read as:

lunch_panoply4_img8

I remember Edward Anderson, sharing with me that there is no need to spare verboseness in the description text, for the exact reasons I’ve mentioned above. So this example is now larger in character size, but for the tradeoff of being arguably easier to read at a glance for any future developers looking to understand this particular spec’s purpose.

lunch_panoply4_img9

The same goes for the refactored example above. It sounds kind of unfamiliar to me to consider changing text inside of a spec_file a refactor, but since I’m changing the structure of the specs without changing any behavior, I need to embrace the fact that technically this is in fact fitting of the definition of a refactor.

Now that we have that tackled, lets get to using our concise Shoulda-Matchers.

Here are a few links I find useful when attempting to refactor specs using the shoulda-matchers gem by thoughtbot:

The documentation

This cheat sheet

A better cheat sheet

And here is a snapshot of my company_spec file once I’ve refactored by swapping tests with shoulda-matchers. I’ve kept the old specs up for the city and state attributes just to demonstrate the concise power of using shoulda-matchers. I’ll be removing these before my Github commit.

lunch_panoply4_img10

And there we have it! A refactor example of a model being covered by Rspec.

I am still learning so much about TDD, so if you have anything to add, especially in what I could further refactor from the code samples above feel free to comment.

In my next post, I’ll be covering how I refactor a controller spec.

Stay tuned…

Advertisements

Categories: Ruby on rails

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s