Earlier this week Mark Simoneau covered the topic of writing specs for controllers. It was a wonderfully informative AirPair hour where he tutored me on how to write proper tests as well as when and how to refactor once the red, green, tests cases were reached.
Anytime we want to refactor, Mark taught that our only purpose should be to make our code as easy to understand as possible. Here are some additional nuggets of understanding that I picked up during our pair.
There is no such thing as “the” pattern
Mark mentioned that there is a tendency among new developers, that can occur when we learn a new technique or add a new tool to our dev chest. He shared that learning to think about our challenge first, and only then selecting the appropriate tool/technique is preferred, over thinking of a problem thru the lens of one tool fitting all situations. Mark mentioned that learning to use a new ‘hammer’ tool and overusing it, can lead to a developer, over time, thinking of every problem as a ‘nail’. Not good.
Keep specs as clear and concise as possible
desribe, its cousin
it blocks are what will explain at a glance what we’re doing inside a group of specs (the ‘describe’ part), in a certain context ( also named ‘context’), and inside of each spec (named ‘it’).
Here’s a quick example that attempts to illustrate the above paragraph:
In the above illustration, we’re describing the create action in our universities_controller. The context allows us to set up cases, and as you can see, our first context is the case where the create action is given valid credentials. The it are the actual specs, and as seen in the above illustration, is testing each step in a create action within the context that every credential is valid.
Red Green Refactor
Like we spoke about at the beginning of this post, refactoring of specs happen after first writing a test that fails in an expected way and passes after we write the code to satisfy the failing spec. Mark mentioned that a refactor is changing how the code reads without altering it’s behavior. This just means that given a random example problem, lets say this one. Add at least 2 integers together that equal an integer of 10.
We could technically start off by writing our implementation something like
10 = 1 + 3 + 4 + 2. This satisfies the requirements of our problem set, and anyone else who looks at this will more than likely understand due to the problem’s simplicity, but will arguably have to work a little harder than if we refactored this problem (still abiding by it’s parameters) like so:
10 = 5 + 5. Both solutions provide a correct answer, but one is clearly more easy to read.
Controller spec terms
Finally, I thought it would be good to explain a few methods I learned the meaning of.
response method: This has to do with HTTP requests/responses, heres an quote from wikipedia describing some of the available HTTP verbs.
Requests a representation of the specified resource. Requests using GET should only retrieve data and should have no other effect. (This is also true of some other HTTP methods.) The W3C has published guidance principles on this distinction, saying, “Web application design should be informed by the above principles, but also by the relevant limitations.” See safe methods below.
Asks for the response identical to the one that would correspond to a GET request, but without the response body. This is useful for retrieving meta-information written in response headers, without having to transport the entire content.
Requests that the server accept the entity enclosed in the request as a new subordinate of the web resource identified by the URI. The data POSTed might be, as examples, an annotation for existing resources; a message for a bulletin board, newsgroup, mailing list, or comment thread; a block of data that is the result of submitting a web form to a data-handling process; or an item to add to a database.
Requests that the enclosed entity be stored under the supplied URI. If the URI refers to an already existing resource, it is modified; if the URI does not point to an existing resource, then the server can create the resource with that URI.
Deletes the specified resource.
I personally find that this makes for a slightly easier read in the Rails Guides the illustration below comes from section 3.2 titled “CRUD, Verbs, and Actions”.
Here are some matchers that we can use to match our expectation responses.
render_template(:edit) for example will assert the controllers edit action template.
redirect_to: root_path asserts that a redirect to has been build in our controller action.
If you find yourself interested in this topic, checkout the full mentor session with Mark via AirPair!