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
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
- fixed failure of
rspec-rails-2.10.1
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
Enhancements
- Add
prepend_beforeandappend_afterhooks (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_OPTSoptions. example.descriptionreturns 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
Enhancements
- Add new
start_withandend_withmatchers (Jeremy Wadsack) - Add new matchers for specifying yields (Myron Marson):
expect {...}.to yield_controlexpect {...}.to yield_with_args(1, 2, 3)expect {...}.to yield_with_no_argsexpect {...}.to yield_successive_args(1, 2, 3)
match_unless_raisestakes multiple exception args
Bug fixes
- Fix
be_withinmatcher to be inclusive of delta. - Fix message-specific specs to pass on Rubinius (John Firebaugh)
rspec-mocks-2.10.0
Bug fixes
- fail fast when an
exactlyorat_mostexpectation is exceeded
rspec-rails-2.10.0
Bug fixes
render_viewscalled in a spec can now override the config setting. (martinsvalin)- Fix
render_viewsfor anonymous controllers on 1.8.7. (hudge, mudge) - Eliminate use of deprecated
process_view_paths - Fix false negatives when using
route_tomatcher withshould_not controlleris no longer nil inconfig.beforehooks- Change
request.path_parameterskeys 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:
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.

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

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 »

