[rspec-users] questions about meta-programming in a shared_examples group

Stephen Bannasch stephen.bannasch at deanbrook.org
Mon May 10 21:48:16 EDT 2010


I've created a shared_examples group that helps me dry up the testing of a large set of similar rails controllers.

These controllers have an html interface but mostly what I am testing with the shared_examples group is the rendering of four 
different forms of xml that relate to running a dynamically created Java Web Start jnlp.

The html reports when running one of the controller specs looks like this:

   Embeddable::DataCollectorsController GET show with mime type of otml
   renders the requested data_collector as otml without error

Here's an example of what one of the controller specs looks like:

http://github.com/stepheneb/rigse/blob/master/spec/controllers/embeddable/data_collectors_controller_spec.rb

   require 'spec_helper'

   describe Embeddable::DataCollectorsController do

     it_should_behave_like 'an embeddable controller'

     def with_tags_like_an_otml_data_collector
       with_tag('OTDataCollector') do
         with_tag('source') do
           with_tag('OTDataGraphable') do
             with_tag('dataProducer')
           end
         end
         with_tag('xDataAxis') do
           with_tag('OTDataAxis')
         end
         with_tag('yDataAxis') do
           with_tag('OTDataAxis')
         end
       end
     end

   end

I love how clearly each controller spec reads now and how the part that is different in the otml rendering stands out.

But I wondered if the way I am using lambdas in the shared_examples helper is fragile and might break if internals in rspec 
change. The meta-programming I did to get some of this to work seemed a bit messy and I was wondering if there was a simpler 
way.

The describe statement in the shared_examples_for 'an embeddable controller' for that example looks like this:

   describe "with mime type of otml" do
     it "renders the requested #{model_ivar_name_lambda.call} as otml without error" do

The beginning of the shared_examples group looks like this:

   http://github.com/stepheneb/rigse/blob/master/spec/support/embeddable_controller_helper.rb

   shared_examples_for 'an embeddable controller' do
     integrate_views

     controller_class_lambda = lambda {
       self.send(:described_class)
     }
     model_class_lambda      = lambda {
       controller_class_lambda.call.name[/(.*)Controller/, 1].singularize.constantize
     }
     model_ivar_name_lambda  = lambda {
       model_class_lambda.call.name.delete_module.underscore_module
     }

     def with_tags_like_an_otml(model_name)
       self.send("with_tags_like_an_otml_#{model_name}".to_sym)
     end

     before(:each) do
       @model_class = model_class_lambda.call
       @model_ivar_name = model_ivar_name_lambda.call
       unless instance_variable_defined?("@#{@model_ivar_name}".to_sym)
         @model_ivar = instance_variable_set("@#{@model_ivar_name}",
           Factory.create(@model_ivar_name))
       end
     end


The method in the controller spec: with_tags_like_an_otml_data_collector is used in the shared_examples group later like this:

   with_tag('library') do
     with_tags_like_an_otml(@model_ivar_name)
   end



More information about the rspec-users mailing list