Toni Leigh
Toni Leigh

Reputation: 4969

How do define a fine grained structure when using Capybara with RSpec where all tests are run after one `visit()` call

I can't work out how to make Capybara with RSpec handle anything more than two levels before my expects.

In RSpec, I can use describe, followed by context followed by it and I can also nest these to provide really good structured output.

In Capybara I get feature then scenario which is synonymous with it? and that's that, straight into expect. The result is that I get started, but then there's a huge blob of expects checking everything on the page. I know I could break these down individually in scenarios but I don't want to call expensive visit calls for each check. There's no reason why there shouldn't be 50 expects checking a page, so bringing some extra structure would be great.

Which keywords would one use at the different levels of the following structure, either in Capybara, or Capybara with RSpec?

<level1> "full page of app"
  // visit the page once here
  <level2> "check headings"
    <level3> "h1 has text ..."
      expect here ...
      expect here ...
    </level>
    <level3> "there are three h2s"
      expect here ...
      expect here ...
    </level>
  </level>
</level>

The crucial bit is visit() - this should only happen once, as it would be hopelessly inefficient to visit once per expect when all the expects are on the same page. Trying before :all and background mean that it only works on the first test, the returned HTML is empty for the rest of the tests.

Upvotes: 1

Views: 132

Answers (2)

Thomas Walpole
Thomas Walpole

Reputation: 49950

The question has changed now to be more specific about the visit, so I'm adding a separate answer.

Each of your <level 3> scenarios are isolated test sections by design and as such each one will need to perform their own visit() - that visit can be in a before(:each) higher up the tree if you want, but each will need to visit the page. This is by design to isolate each test from each other. You can perform multiple expects in each <level 3> if that makes sense for whatever is being tested, or you could factor multiple expects out into methods like verify_widget_is_displayed_correctly.

One other thing to consider is that depending on what all those expects are testing are you may want to be verifying some of them in view tests (which Capybara's matchers are available in by default as of Capybara 2.5) rather than in integration tests. Integration (feature) tests really are about verifying the behavior of the app as the user clicks around rather than minute details of the views layout.

Upvotes: 1

Thomas Walpole
Thomas Walpole

Reputation: 49950

When using Capybara with RSpec you're not using Capybara instead of RSpec you are using RSpec with some extra stuff thrown in by Capybara. As such you can still use context, describe, it and nest them just like you can when using RSpec without Capybara. Capybara adds sugar on top but 'feature' is just the same as 'describe' or 'context' with type: 'feature' set. 'scenario' is just an alias for 'it', 'fscenario' is just 'it' with focus: true metadata set, and 'xscenario' is 'it' with skip metadata set

You can see it here - https://github.com/jnicklas/capybara/blob/master/lib/capybara/rspec/features.rb

Upvotes: 1

Related Questions