Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Patterns for accessing subject hierarchy in RSpec

When using RSpec to test deeply nested data structures, I find the need to define subjects in nested contexts in terms of the subjects in the containing contexts. I have looked extensively but not found any examples on how to do with without defining many variables. It complicates the specs and limits the possibility of spec reuse. I am curious whether there is a way to do this in RSpec as it stands and, if not, what would be a good way to approach the problem.

Right now, my code looks something like:

context 'with a result which is a Hash' do
  before do
    @result = get_result()
  end
  subject { @result }
  it { should be_a Hash }
  context 'with an Array' do
    before do
      @array_elem = @result[special_key]
    end
    subject { @array_elem }
    it { should be_an Array }
    context 'that contains a Hash' do
      before do
        @nested_hash = ...
      end
      subject { @nested_hash }
      ...
    end
  end
end

Instead, I'd rather write something along the lines of:

context 'with a result which is a Hash' do
  subject { get_result }
  it { should be_a Hash }
  context 'with an Array' do
    subject { parent_subject[special_key] }
    it { should be_an Array }
    context 'that contains a Hash' do
      subject { do_something_with(parent_subject) }
      ...
    end
  end
end

What's a way to extend RSpec with this type of automatic subject hierarchy management?

like image 588
Sim Avatar asked Sep 23 '11 05:09

Sim


1 Answers

I was looking for the same kind of thing, and wanted to use subject so that I could use its, so I implemented it like this:

describe "#results" do
  let(:results) { Class.results }

  context "at the top level" do
    subject { results }

    it { should be_a Hash }
    its(['featuredDate']) { should == expected_date }
    its(['childItems']) { should be_a Array }
  end

  context "the first child item" do
    subject { results['childItems'][0] }

    it { should be_a Hash }
    its(['title']) { should == 'Title' }
    its(['body']) { should == 'Body' }
  end

  context "the programme info for the first child item" do
    subject { results['childItems'][0]['programme'] }

    it { should be_a Hash }
    its(['title']) { should == 'title' }
    its(['description']) { should == 'description' }
  end
end
like image 95
Shevaun Avatar answered Nov 15 '22 03:11

Shevaun