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:
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