Pair programming session for Ruby on Rails code and using RSpec's tagging system

June 1, 2023

Obie Fernandez requested a pair programming session for Ruby on Rails code. He also needed help with using RSpec's tagging system to run before and after hooks on certain specs. The assistant provided guidance on how to achieve this and also helped with making a `let` statement available in all specs.

Mike Nichols
Pair Programmer

Need some help with RSpec. I'm using a library called StripeMock and I want to run the following before and after hooks on certain specs, only if they're tagged with :striped or something like that

Obie Fernandez over 1 year ago

Sure, Obie. To run before and after hooks on certain specs tagged specially, you can use RSpec's tagging system. You can simply add before and after hooks with :striped metadata to whatever block of tests you'd like to run those hooks on. Here's an example:

RSpec.configure do |config|

config.before(:example, :striped) do
# Code to run before striped specs
end

config.after(:example, :striped) do
# Code to run after striped specs
end

end

Let me know if that helps, or if you need further assistance.

Mike Nichols over 1 year ago

that really helps actually!

Obie Fernandez over 1 year ago

Glad to hear that, Obie! Is there anything else I can help you with?

Mike Nichols over 1 year ago

where do I put :striped in the spec itself

Obie Fernandez over 1 year ago

You can put :striped above the spec block in the describe block like this:

describe "my StripeMock spec", :striped do
  it "does something with StripeMock" do
    # test code here
  end
end

By using the tagging system along with the before and after hooks, you can run specific code on certain specs only.

Mike Nichols over 1 year ago

is it possible to put a let statement into rails_helper so that it's available in all specs? if not then how would I accomplish this being available to all specs let(:stripe_helper) { StripeMock.create_test_helper }

Obie Fernandez over 1 year ago

Yes, it's possible to put a let statement into rails_helper so that it's available in all specs.

You can simply add the let(:stripe_helper) { StripeMock.create_test_helper } statement to the Rails.configure block in rails_helper.rb like so:

Rails.configure do |config|
  # other configurations

  config.before(:suite) do
    # This runs once before all specs
    StripeMock.create_test_helper
  end

  config.after(:suite) do
    # This runs once after all specs
    StripeMock.stop_client
  end

  config.include Stripe::TestHelper, type: :feature
  config.include FactoryBot::Syntax::Methods

  # add let statement here
  config.before(:each) do
    let(:stripe_helper) { StripeMock.create_test_helper }
  end
end

This will include the stripe_helper method in all your specs.

Mike Nichols over 1 year ago

That generated an error

     Failure/Error: let(:stripe_helper) { StripeMock.create_test_helper }
       `let` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block).
     # ./spec/rails_helper.rb:46:in `block (2 levels) in <top (required)>'
Obie Fernandez over 1 year ago

Thanks for letting me know, Obie. It looks like the let statement cannot be used within the config.before(:each) block. You can try a different approach by using a before(:all) hook and define your stripe_helper method as a class method. Here's an example:

RSpec.configure do |config|
  # other configurations

  config.before(:suite) do
    # This runs once before all specs
    StripeMock.create_test_helper
  end

  config.after(:suite) do
    # This runs once after all specs
    StripeMock.stop_client
  end

  # add before(:all) hook here
  config.before(:all) do
    def self.stripe_helper
      @stripe_helper ||= StripeMock.create_test_helper
    end
  end
end

This way, you can access stripe_helper as a class method in all your specs.

Mike Nichols over 1 year ago