You might find yourself running the same test in RSpec using slightly different conditions. SOMETHING like this:

# RSpec test code

describe "some test" do
  context "attr == 1" do
    before do
      object.attr = 1
    end

    specify do
      expect {
        object.some_long_method_name
      }.to raise_error RuntimeError
    end
  end

  context "attr == 2" do
    before do
      object.attr = 2
    end

    specify do
      expect {
        object.some_long_method_name
      }.to raise_error RuntimeError
    end
  end
end

If possible, I try to group such tests together using arrays e.g.

# RSpec test code

describe "some test" do
  [1, 2].each do |i|
    context "attr == #{i}" do
      before do
        object.attr = i
      end

      specify do
        expect {
          object.some_long_method_name
        }.to raise_error RuntimeError
      end
    end
  end
end

In the code above, I’ve separated the tests by context so the results appear under different headings. This helps analyze the results and quickly figure out which array-iteration a particular set of results belongs to.

This array-with-context-separation works for me as long as I don’t have varying before-block for each iteration. In this case, I wrap my expectation in a named subject like so:

# RSpec test code

describe "some test" do
  subject(:test_it) do
    expect {
      object.some_long_method_name
    }.to raise_error RuntimeError
  end

  context "something weird 1" do
    before { # some weird operations }
    specify { test_it }
  end

  context "something weird 2" do
    before { # some more weird operations }
    specify { test_it }
  end
end

You could do the same with ‘let’ variables instead of using a named subject. But ‘let’ is usually used (and more suited) to test data. Another approach would be to use ‘after’ blocks or even custom-matchers, depending on the scenario. But I usually opt for the subject-approach.