On Jul 26, 2010, at 8:55 am, Wincent Colaiuta wrote:

> Seems to me that including the same shared example group twice in the same 
> "describe" block is a bit of an abuse, to be honest. I don't think it was 
> ever really intended to be used in that way.

You're right, it clearly wasn't intended for this.  I'm trying to find the best 
way to express the behaviour I want without bending the current syntax of RSpec 
too much.  This is indeed a toy example, so let me explain the real situation 
in more detail.

I'm doing a small side project to make a checklist app.  As part of that, I'm 
trying to extract out a library similar to Naked Objects[1].  One of the things 
that can be factored out is collections inside entities.  So I currently have, 
as examples:

  class User
    extend DomainLib::Entity::ClassExtensions
    include DomainLib::Entity::InstanceExtensions

    collection :checklist_templates, of: :checklist_template, class_name: 
"ChecklistTemplate"
  end

and

  class ChecklistTemplate
    extend DomainLib::Entity::ClassExtensions
    include DomainLib::Entity::InstanceExtensions
  
    collection :items, of: :item, class_name: "ChecklistTemplateItem"
  end

Now one of the thing that bugs me about using ORM (eg ActiveRecord, DataMapper) 
features for this is you're then faced with the dilemma of do you do an 
integration test of the collection functionality, which duplicates a lot of the 
testing effort put into the ORM, or do you mock this out, and risk having false 
positives because the ORM behaves differently than your test setup assumes?

The solution I'm playing with is to extract shared contract (ie shared example 
groups) that you can mix into a spec for a host class (eg User, Checklist) 
above to prove the feature (here collections) works, without reference to the 
implementation.  (The specs inside DomainLib prove the general case.)

With the help of this spec_helper incantation:

  module SpecHelperObjectExtensions
    def contract(name, &block)
      shared_examples_for(name, &block)
    end
  end
  include SpecHelperObjectExtensions

  RSpec.configure do |c|
    c.alias_it_should_behave_like_to(:it_satisfies_contract, 'satisfies 
contract:')
  end

I've already been able to extracted contract, which is for Representation 
(basically, a view object that isn't much more than a Struct):

  # Params:
  # * representation_class
  # * properties
  contract "Representation" do
    # ...
    # Setup and other examples omitted
    # ...
    
    describe "#==" do
      it "is true for Representations with the equal attributes" do
        representation_class.new(default_attributes).should eq 
representation_class.new(default_attributes)
      end
    
      it "is false if any property is different" do
        properties.each do |property|
          representation_class.new(default_attributes).should_not eq(
            
representation_class.new(default_attributes_with_different_value_for(property))
          )
        end
      end
    end

  end

This is fine for a class, but the behaviour I want to prove with a Collection 
needs to be mixed in once per collection, eg (the last two are made up):

  describe User do
    it_satisfies_contract "Entity Collection", for: "checklist_templates"
    it_satisfies_contract "Entity Collection", for: "groups"
    it_satisfies_contract "Entity Collection", for: "delegated_actions"
  end
  
>  describe Integer do
>    [1, 2].each do |i|
>      describe i do
>        it_should_behave_like 'Comparable'
>      end
>    end
>  end
> 
> ...
> 
> I know you probably have some real example in mind hiding behind that toy 
> example, but I believe anything you want to test can be written in the same 
> way (ie. without needing to inject the "<i>" into your shared examples).

So as you can see, in the real (non-toy) example there's no object to be 
described: it's an aspect of behaviour of the test subject, and one than can 
occur N times.  I'm aware that I'm twisting RSpec quite a bit to try to achieve 
this.

If you (or anyone) have any thoughts though, I'd love to hear them.  This one 
is messing with my head a bit :)

Cheers
Ash


[1] http://www.nakedobjects.org/


-- 
http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to