Spec smell: explicit use of subject »

Created at: 14.05.2012 05:13, source: David Chelimsky, tagged: Uncategorized

TL;DR

Explicit use of the “subject” abstraction is a code smell, and should be refactored to use a more intention revealing name whenever possible.

One liners

rspec-core supports a one-liner syntax to reduce the noise of common requirements like validations:

Without support for this syntax, the same example might look like this:

The benefit of this more verbose example is that it we can read it and understand all the parts right away: an object is initialized and assigned to a local variable, then that variable is used for an expectation.

The benefit of the one-liner is that it’s terse and expressive, but that comes at a cost: you can’t see what the expectation is being evaluated against, so you have to understand some underlying mechanics in order to isolate/understand a failure.

The subject abstraction

Behind the scenes, the one-liner uses a “subject” abstraction supported by two methods named subject. One is a class method on ExampleGroup, used to declare the “subject” of all of the examples in the group:

The other is an instance method on ExampleGroup. The first time it is called within an example the block passed to the class’ subject method is evaluated and its result memoized, returning the same value from that and each subsequent subject call:

Here is what they look like together:

The problem with this example is that the word “subject” is not very intention revealing. That might not appear problematic in this small example because you can see the declaration on line 3 and the reference on line 6. But when this group grows to where you have to scroll up from the reference to find the declaration, the generic nature of the word “subject” becomes a hinderance to understanding and slows you down.

In this case, we’d be better served by using a method (or a let declaration) with an intention revealing name:

If we can do that, you might wonder why we have “subject” at all. Well, it was originally designed to never be seen:

Implicit subject

Note in the example with subject { Article.new }, that the subject declaration is initializing an Article with no args. Since RSpec knows that the first argument to describe is the Article class, it can store a similar block in the background as a default, implicit subject declaration, leaving us with:

That’s a little better, but now subject appears out of nowhere in the example, leaving the reader to wonder where it came from. To remove the need for explicitly referencing subject, the example delegates should and should_not to subject when it is, itself, the receiver:

Starting that line with “should” seems a bit odd though, so the final step is to do it all in one line:

Now we have a completely implicit subject, and the result reads quite nicely in both the code and the output when run with --format documentation:

Article
  should validate presence of :title

We still need to trust that something is doing some work for us but it’s all operating at the same level of abstraction, so we don’t have to try to interpret half of the functionality.

Avoid explicit use of subject

Intention revealing names are crucial if you want to be able to quickly scan and understand code as you navigate around different parts of a system. This is as true for specs as it is for implementation, and the generic nature of the word “subject” makes it a poor choice when a more intention revealing name can be used.

Is an explicit subject ever OK?

Guidelines are guidelines; YMMV. In general I would recommend that if there is a reasonable way to use an intention revealing name instead of “subject”, you should. The only use case I can think of in RSpec in which another name can’t be used is the one liner syntax:

Here we have to use subject because that’s the only way to tell RSpec where to send should and should_not. In my opinion, any other explicit appearance of subject can and should be refactored to use an intention revealing name.

Update 2012-05-15

Based on feedback on this post, I added support for a “named subject,” which lets you reference the declared subject implicitly in one-liners and with an intention revealing name in standard examples:

This will be released with rspec-core-2.11. Keep your eyes out for it!


more »

rspec-mocks and rspec-rails-2.10.1 are released! »

Created at: 05.05.2012 09:34, source: David Chelimsky, tagged: Uncategorized

These are patch releases recommended for anybody who has already upgraded to 2.10.

rspec-mocks-2.10.1

full changelog

Bug fixes

  • fix regression of edge case behavior
    • fixed failure of object.should_receive(:message).at_least(0).times.and_return value
    • fixed failure of object.should_not_receive(:message).and_return value

rspec-rails-2.10.1

full changelog

Bug fixes


more »

rspec-2.10 is released! »

Created at: 04.05.2012 04:29, source: David Chelimsky, tagged: Uncategorized

API Docs (RDoc)

http://rubydoc.info/gems/rspec-core
http://rubydoc.info/gems/rspec-expectations
http://rubydoc.info/gems/rspec-mocks
http://rubydoc.info/gems/rspec-rails

Cucumber docs

http://relishapp.com/rspec/rspec-core
http://relishapp.com/rspec/rspec-expectations
http://relishapp.com/rspec/rspec-mocks
http://relishapp.com/rspec/rspec-rails

rspec-core-2.10.0

full changelog

Enhancements

  • Add prepend_before and append_after hooks (preethiramdev)
    • intended for extension libs
    • restores rspec-1 behavior
  • Reporting of profiled examples (moro)
    • Report the total amount of time taken for the top slowest examples.
    • Report what percentage the slowest examples took from the total runtime.

Bug fixes

  • Properly parse SPEC_OPTS options.
  • example.description returns the location of the example if there is no explicit description or matcher-generated description.
  • RDoc fixes (Grzegorz Świrski)
  • Do not modify example ancestry when dumping errors (Michael Grosser)

rspec-expectations-2.10.0

full changelog

Enhancements

  • Add new start_with and end_with matchers (Jeremy Wadsack)
  • Add new matchers for specifying yields (Myron Marson):
    • expect {...}.to yield_control
    • expect {...}.to yield_with_args(1, 2, 3)
    • expect {...}.to yield_with_no_args
    • expect {...}.to yield_successive_args(1, 2, 3)
  • match_unless_raises takes multiple exception args

Bug fixes

  • Fix be_within matcher to be inclusive of delta.
  • Fix message-specific specs to pass on Rubinius (John Firebaugh)

rspec-mocks-2.10.0

full changelog

Bug fixes

  • fail fast when an exactly or at_most expectation is exceeded

rspec-rails-2.10.0

full changelog

Bug fixes

  • render_views called in a spec can now override the config setting. (martinsvalin)
  • Fix render_views for anonymous controllers on 1.8.7. (hudge, mudge)
  • Eliminate use of deprecated process_view_paths
  • Fix false negatives when using route_to matcher with should_not
  • controller is no longer nil in config.before hooks
  • Change request.path_parameters keys to symbols to match real Rails environment (Nathan Broadbent)
  • Silence deprecation warnings in pre-2.9 generated view specs (Jonathan del Strother)


more »

In Case You Missed It: January’s JRuby Meetup »

Created at: 27.01.2012 23:36, source: Engine Yard Blog, tagged: Uncategorized

If you weren't able to make it to our JRuby Meetup last week at Engine Yard HQ, you missed out on an awesome presentation from Square platform engineer Xavier Shay. However, you're in luck! Our favorite videographers at Marakana (a big shout out and thank you to Max Walker!) taped the whole thing. And of course, a big thanks to Xavier for coming and chatting about Square's awesome technology! Hear about how Square incorporated JRuby, Kirk, Jetty and Jetpack into their platform.

Check out the video and slides right here:


Also, if you haven't already heard, JRuby Conf 2012 is going to be in the lovely Minneapolis, MN on May 21-23! Check out the brand new website to find out more!


more »

Introducing the Early Access Features page »

Created at: 02.12.2011 02:01, source: Engine Yard Blog, tagged: Engine Yard Cloud Product Uncategorized

Last week, we announced Node.js support as part of our Labs program. At the beginning of this month, we also released early access to Ruby 1.9.3, and our data team is doing great work expanding our stack.

Previously, we asked you to sign up through various pages, and you would have needed to wait for us to grant your access. Today, we’re ready to give you easier control of these features. From the Early Access Features page, you’ll be able to manage these new features on your own. When you visit your account settings, you will see a button at the bottom of the page.

Manage Early Access Features

Now, using Engine Yard Labs and Alpha features will be as easy as turning on a switch!

Early Access Features page

For our current features in early access, you can still use our sign up pages to have them enabled for you if you choose, but we think this will make it much easier for you to try out. As always, feel free to let us know what you think at our feedback Google Group!


more »