Search code examples
rspec

Is it possible to combine RSpec shared examples with "it" blocks, and therefore not triggering the context to run twice


I've got a bunch of integration tests that have one part that can be shared across most tests, and a specific part that is specific to any one test. These integration tests run against an external system and as such is quite slow. When using shared examples to cover the shared parts, and an "it" block to cover the specific parameters, this, in essence, creates two "it" blocks, causing the context to run twice. Effectively doubling the time it takes to run these suites. Is there any way around this?

Example below:

RSpec.shared_examples 'my_shared_example' do
  it 'expects' do
    expect(parameter).to eq(expected_paramter)
  end
end

RSpec.describe MrmCampaignService, integration: true do
  context 'my context' do
    include_examples 'my_shared_example'

    it 'expects these things also' do
      expect(specific_parameter).to eq(expected_specific_paramter)
    end
  end
end

Each time 'my context' runs, both 'it' blocks run independantly. Is it possible to essentially include the shared_example within the it block? Or in essence "combine" the 'it' blocks into one?

Thanks


Solution

  • You cannot run one it block inside another it block. So, the direct answer to your question is no.

    You mention that the context executes twice, once for each test. This is normal. let and before statements are executed once for every it block to ensure that the test has a valid environment in which to run.

    The advice I would give you here is that when testing external services, it is faster (and will produce less flaky tests) if you mock the service and test that you are sending it the right messages with the right parameters. This will produce a test that executes quickly and reliably. Then you can have a very small (1) number of actual integration tests (if warranted) to ensure that the contract between you and the external service hasn't changed.