right on the fly (reuse is cu-cumbersome) • Gherkin breaks editors • Business people don’t actually use them… • Parsing natural language into code is a mental overhead Cucumber is OK, but: Integration Testing w/ Page Objects | @dorian_escplan | @hashrocket
is broken • what do I write next? • Tests are brittle • Hard to read (too low level, not declarative) R Integration Testing w/ Page Objects | @dorian_escplan | @hashrocket
Martin Fowler’s Blog (WindowDriver 2004, PageObject 2013) • Popularized by the official Selenium documentation as a solution for reducing test maintenance and reducing code duplication. • Not very well known Integration Testing w/ Page Objects | @dorian_escplan | @hashrocket
It has the downside 2 # of increasing the boot-up time by auto-requiring all files in the support 3 # directory. Alternatively, in the individual `*_spec.rb` files, manually 4 # require only the support files necessary. 5 # 6 # Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
It has the downside 2 # of increasing the boot-up time by auto-requiring all files in the support 3 # directory. Alternatively, in the individual `*_spec.rb` files, manually 4 # require only the support files necessary. 5 # 6 Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
It has the downside 2 # of increasing the boot-up time by auto-requiring all files in the support 3 # directory. Alternatively, in the individual `*_spec.rb` files, manually 4 # require only the support files necessary. 5 # 6 Dir[Rails.root.join(‘spec/support/pages/*.rb')].each { |f| require f }
def initialize(product) @product = product end def on_page? has_selector?('#productTitle', text: @product.name) end def has_price?(amount) has_selector?('#priceblock_ourprice', text: amount) end def visit_page visit product_path(@product) end end end
11643 F Failures: 1) User remains signed in when visiting root page (login) user is redirected to posts index Failure/Error: expect(posts_index).to be_on_page expected `#<Pages::PostsIndex:0x007fb71bbe4bf8>.on_page?` to return true, got false # ./spec/features/user_signs_in_spec.rb:60:in `block (2 levels) in <top (required)>' Finished in 0.52679 seconds (files took 2.47 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/features/user_signs_in_spec.rb:50 # User remains signed in when visiting root page (login) user is redirected to posts index Randomized with seed 11643
28431 F Failures: 1) User remains signed in when visiting root page (login) user is redirected to posts index Failure/Error: has_selector?(:css, 'h1', text: 'Index') expected to find css "h1" with text "Index" but there were no matches. Also found "Posts", which matched the selector but not all filters. # ./spec/support/pages/posts_index.rb:7:in `on_page?' # ./spec/features/user_signs_in_spec.rb:60:in `block (2 levels) in <top (required)>' Finished in 0.50323 seconds (files took 3.01 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/features/user_signs_in_spec.rb:50 # User remains signed in when visiting root page (login) user is redirected to posts index Randomized with seed 28431
when to expose predicate methods • Prefer user language when modeling page objects • A page object does not have to represent a single page • Don't make a method on a page object do too much Integration Testing w/ Page Objects | @dorian_escplan | @hashrocket
and reusable abstraction • Try them out gradually by refactoring existing tests • Give the `include Capybara::DSL` approach a try first • CapybaraErrorIntel will let you enjoy the best of both worlds Integration Testing w/ Page Objects | @dorian_escplan | @hashrocket