Today, we’ll be covering project lunch_panoply‘s test coverage of controller actions. I’ll be doing a refactor of the model specs and controller specs in a future post.
I’ve been reading a really good ebook entitled Everyday Testing with Rspec: A Practical Approach to Test-driven Development by: Aaron Sumner. It has been extremely helpful in helping me to understand the various nuances to providing good test coverage for a Rails application. I especially found a lot of value in Aaron’s example specs, as well as the test environment setup. I wasn’t using the database_cleaner gem until I purchased his book.
What to Test in a Controller Spec
There are 3 things I’m learning to test inside of my controller action specs:
- Testing Controller Response
- Testing Returned Data
- Testing Redirects, and Renderings in a Controller Action
We’ll be covering each of these three controller behaviors up next.
Testing Controller Responses
Part of a basic controller spec’s coverage should usually include that a controller method returns the HTTP status code we are expecting. It’s also a good idea to include whether we’re expecting a redirect upon success or which view template to render if the spec calls for it.
Lets have a look at an example or two:
Above I’ve just shown an illustration of how to setup a controller spec. If we recall from my last post, there are 3 main steps to setting up any spec.
- The Setup: Where we establish the scenario typically with Factories
- The Execution: Creating a method call that triggers the spec to be ran
- The Verification: We make an assertion to verify our expected results
With this in mind, lets fill out the empty spec block from above:
In line: 7, I’m setting up a Factory instantiation. I’m not using
employee = FactoryGirl.create(:employee) because of the configurations available in FactoryGirl to truncate its syntax.
Here’s where and what I’ve added to my spec_helper file.
It is line: 12 that provides the ability to drop the
FactoryGirl from every
.build method we’ll use in the future.
line: 8 (from the gist before the spec_helper illustration) declares the appropriate HTTP verb and also passes in the parent_id of an Employee. In this case Employee’s parent is a company. Since this is the index action, we don’t need a particular id to pass in for an employee, as all employee objects will be displayed here.
Lines: 9 – 10 is where we make our assertions. We are expecting http success in line: 9 and that this controller action includes a rendering of the :index view. Here’s a look at the actual controller to verify:
And a quick snapshot of the Rails Guides to explain how
render automatically includes the :index template even though it’s not specified inside of the above controller action:
Testing Returned Data
Ruby on Rails allows us to verify the data generated by our controller action through 4 collections; assigns, session, cookies and flash. Assigns is typically used most often.
Lets look at how the
new controller action is setup:
In the above example we can see that I have separated
it 'returns http success' and
it 'renders the :new template into separate specs. Something to keep in mind for our refactor post I’d say.
More importantly we can see that the spec
it 'assigns a new Employee to employee' is using
assigns(:employee) pseudo-hash variable in it’s assertion on line: 37. We’re asserting that we are expecting a new instance of Employee to actually be from the class Employee.
assigns variable allows us access to any instance variable set in the controller method.
Testing Redirects and Renders
We’ve already seen a good example of an assertion to validate a template rendering, and some thorough documentation to best explain whats happening when no call to
render in a controller action method is explicitly made.
Lets have a quick look over a few redirect assertions:
I’ve included the entire
update action block as an example, inside of the block we’re testing for the location of a specific employee resource representative, covering the case of an employee successfully updating their attributes, and lastly the successful redirect to an employee with updated attributes.
Lets walk through the last spec inside of the
with valid attributes context.
on line: 111 we’re just setting up our object via a factory, line: 112 is defining the appropriate HTTP verb, passing in the parent_id and object_id, for routing purposes, and also passing the specific employee attributes that were updated. Finally, we’re asserting that the response should redirect to our employee :show template by listing its associated path name.
Here’s a look at our
update controller action with invalid attributes:
I like to imagine myself clicking through the application in order to give me a better sense of the behaviors I’m expecting and guarding against when I’m laying out my pending specs. For instance, we know that if we are at a form on an employee
edit page, and update a value with another appropriate value, we are expecting to be redirected back to the
show page typically. If we somehow enter in some invalid data/data-type (i.e. accidentally deleting a form_field with a presence validation defined inside it’s model), the convention is for the resourced representation to be re-rendered on the
edit page with an error displaying, letting us know our mistake.
I hope that this post on Controller specs have been as insightful for you to read as it was for me to write.
This post wouldn’t be complete without running both of the two contoller_specs I’ve completed so far.
Here’s the output:
Looks green enough to me! Time to push this to github!
Next up, the refactor.
Categories: Ruby on rails