Rspec-core: Run the same spec multiple times w/ different filters

Created on 8 Oct 2011  ·  3Comments  ·  Source: rspec/rspec-core

_Disclaimer: This request specifically stems from doing JavaScript acceptance tests with Capybara. Although I can see use cases for other situations._

All of my applications are coded so that they work fine with JS turned off, but with JS turned _on_, you get a lot of nice bells and whistles to make the user experience more pleasant. Because of this, from the user's point of view, the interactions on most things are identical; however I want to test that it works both w/ and w/o JS.

What I'd like is to be able to do is set some sort of flag to tell RSpec to run the same spec twice w/ each filter set. Something like:

it 'does this same thing with and without JS enabled', :run_with => [{:js => true}, {:js => false}] do
    # stuff here
end

I know this can be accomplished with shared examples but the resulting code is not very elegant.

It could additionally be used if you wanted to test w/o JS (Rack test) w/ JS on Firefox (Selenium) and w/ JS on Webkit (capybara-webkit) like this:

it 'does this same thing with and without JS enabled', :run_with => [{:js => false}, {:driver => :selenium}, {:driver => :webkit}] do
    # stuff here
end

I'm also envisioning a way to use custom filters to specify the run_with options so it's not quite so verbose such as:

it 'does this same thing with and without JS enabled', :run_with_all_drivers => true do
    # stuff here
end

Thoughts? I looked through the docs and the code and didn't see a way to currently do this with filters.

Most helpful comment

Filters aren't really designed to do this out of the box, but it's not difficult to get the behavior you're asking for w/o us making changes to RSpec:

[true, false].each do |js|
  it 'does this same thing with and without JS enabled', :run_with => {:js => js } do
    # stuff here
  end
end

If this is a common pattern you need, you can create a little DSL method for it:

module WithAndWithoutJS
  def with_and_without_js(&block)
    [true, false].each do |js|
      context "with :js => #{js}", :run_with => { :js => js } do
        module_eval(&block)
      end
    end
  end

  RSpec.configure { |c| c.extend self }
end

Then you can use this method like so:

describe "My integration spec" do
  with_and_without_js do
    it "does something with and without js" do
    end
  end
end

I think this is farely elegant. Changing how filters work to do what you're asking would be a fairly significant change that would add a future maintenance burden to the RSpec team for a feature that I would expect to be rarely used, so my instinct is to not add this to core.

That said, if you want to create an rspec-multi-filters gem that provides this functionality, feel free :).

All 3 comments

Filters aren't really designed to do this out of the box, but it's not difficult to get the behavior you're asking for w/o us making changes to RSpec:

[true, false].each do |js|
  it 'does this same thing with and without JS enabled', :run_with => {:js => js } do
    # stuff here
  end
end

If this is a common pattern you need, you can create a little DSL method for it:

module WithAndWithoutJS
  def with_and_without_js(&block)
    [true, false].each do |js|
      context "with :js => #{js}", :run_with => { :js => js } do
        module_eval(&block)
      end
    end
  end

  RSpec.configure { |c| c.extend self }
end

Then you can use this method like so:

describe "My integration spec" do
  with_and_without_js do
    it "does something with and without js" do
    end
  end
end

I think this is farely elegant. Changing how filters work to do what you're asking would be a fairly significant change that would add a future maintenance burden to the RSpec team for a feature that I would expect to be rarely used, so my instinct is to not add this to core.

That said, if you want to create an rspec-multi-filters gem that provides this functionality, feel free :).

@myronmarston as usual, it was just my ignorance of what RSpec could do. Thanks for taking the time out and clarifying. I think this will work nicely. :)

:+1: awesome

Was this page helpful?
0 / 5 - 0 ratings