specin rspec with rails

Posted by Tammer Saleh

Mar 09

Using rSpec / Spec::Rails

Installation is pretty simple, and is fully covered here.

Here’s an example of some reasonable specs for a product model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
context "An instance of Product" do
  fixtures :products

  setup do
    @product = Product.find(:first)
  end

  specify "should return lowest of list_price or our_price when sent price" do
    @product.should_receive(:our_price).and_return(1)
    @product.should_receive(:list_price).and_return(2)
    @product.price.should == 1
  end

  specify "should return highest of price or map_price when sent visible_price" do
    @product.should_receive(:map_price).and_return(1)
    @product.should_receive(:price).and_return(2)
    @product.visible_price.should == 2
  end

  specify "should find love" do
    "shot down".should == "to be loved"
  end
end

This is just one context from the file. Here’s a screenshot of the output from the whole specification:

rspec output

Note the delicate curves of colorization. Note the simplicity of the context/specification structure. Wonderful stuff, here.

Extending rSpec

Any good testing library needs to be easily extendable—adding assertions, custom test methods, and all kinds of helpers really eases the developer’s fingers. To that end, I ported some of my model test helpers to rSpec. Here’s how they’re used:

1
2
3
4
5
6
7
8
9
10
11
context "The Product class" do
  model_class Product

  test_required_attributes :title, :sku
  test_unique_attributes :sku
  test_has_and_belongs_to_many :categories, :web_categories, :articles, 
                               :related_products, :accessories, :related_to_products
  test_has_many :alternate_images, :vendables, :synonyms, :metatags
  test_has_many :vendors, :through => :vendables
  test_has_one :image  
end

And you can see the output in the screenshot above. Line 6 alone autogenerates six different specifications. This is very useful.

Unfortunately, getting this to work with rSpec is way more difficult than it should be. There are two root problems (as far as I can tell):

  1. The context method is defined on Kernel. This feels dirty, and means that any methods you’d like to add alongside context also have to be in Kernel. I don’t think it would have caused too much typing to have to wrap your contexts in a class.
  2. The context of the context block is an object instance, making it fairly difficult to wrap your head around exactly where you should be putting your extra code. The only source of information I could find about customizing rSpec suggests overriding before_context_eval. This would work for your own helpers, but not for third-party plugins (as they would override each other’s changes).

I finally got my plugin working while using the spec command, only to see it break everything horribly with the rake spec command (which seems to use a completely different Spec::Runner class). Not good, and giving up.

Final Opinions

Pros:

Cons:

While I really like the work the rSpec team is doing, and I expect to see more improvements and cool features fairly soon, the issues above were enough to convince me that it’s just not yet ready for me to recommend to my coworkers. I’m open to debate or commentary, so if you think I’ve missed anything, just let me know.


Comments on this post

evan

Mar 09

evan said,

Some of those into testing methodologies in my groups have moved to test/spec. For me it’s basically a wash. I write Test::Unit tests in a behavioral way (always have) and everything is fine.

Tammer Saleh

Mar 09

Tammer Saleh said,

Evan: Thanks for the pointer.

I’m definitely looking at Test::Spec next, as well as Spec::Unit. If I go with the latter, I’m sure I’ll have to make some changes to get it to behave just the way we’d like.

Luis Lavena

Mar 10

Luis Lavena said,

Tammer:

I like how you DRYed your specs. I’ve been feeling a bit off “ruby way” since migrated from Test::Unit to rSpec.

Will try to reverse engineer your test_ methods ;-)

Thanks for this helpful post!

Tammer Saleh

Mar 10

Tammer Saleh said,

Luis,

I didn’t want to clutter the article with the helpers I had written, but here they are: http://p.caboo.se/46045

You should be able to just add them into the spec_helper.rb file.

Two caveats: I stole a good deal of code from other snippets to make them and I intend to make these into a Test::Unit plugin of some sort


Sorry, comments are closed for this article.

© 2000 - 2009 by thoughtbot, inc.
written by a bushel of tiny robots