{"id":1213,"date":"2012-01-08T01:15:54","date_gmt":"2012-01-07T23:15:54","guid":{"rendered":"http:\/\/blog.railsware.com\/?p=1213"},"modified":"2021-08-12T13:34:55","modified_gmt":"2021-08-12T10:34:55","slug":"capybara-with-givenwhenthen-steps-in-acceptance-testing","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/capybara-with-givenwhenthen-steps-in-acceptance-testing\/","title":{"rendered":"Capybara with Given\/When\/Then steps in acceptance testing"},"content":{"rendered":"\n<p>Capybara with Given\/When\/Then steps in acceptance testing.<\/p>\n\n\n\n<p>Many of us use <a href=\"http:\/\/cukes.info\/\">cucumber<\/a> to write acceptance tests.<br>We must to say it&#8217;s very nice tool that allows you to write features in English plain text.<br>The main goal is provide interface that should be clear for Customer(non-programmer) and Developer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Cucumber example:<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">Feature: User signup\n  As a user\n  I want to sign in\n  So I can use service features\n\n  Background:\n    Given user with \"jack@daniles.com\" email and \"qwerty\" password\n\n  Scenario: Signing in with correct credentials\n    When I go to sign in page\n    And I fill in \"email\" with \"jack@daniles.com\"\n    And I fill in \"password\" with \"qwerty\"\n    And I click \"Login\" button\n    Then I should see \"Welcome, jack@daniles.com!\"\n\n  Scenario: User tries to sign in with incorrect password\n    When I go to sign in page\n    And I fill in \"email\" with \"jack@daniles.com\"\n    And I fill in \"password\" with \"bla\"\n    And I click \"Login\" button\n    Then I should see \"Invalid credentials\"<\/pre>\n\n\n\n<p>It&#8217;s very readable. But cucumber has one big downside:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Steps maintenance<\/pre>\n\n\n\n<!--more-->\n\n\n\n<p>All steps are global and a instance variable from one step is accessible in another step.<br>In big project it can easy lead to mess.<br>Also you can read some rants about cucumber:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/www.software-testing.com.au\/blog\/2010\/08\/31\/does-cucumber-suck\/\">Does cucumber suck?<\/a><\/li><li><a href=\"http:\/\/blog.codegram.com\/2011\/5\/why-cucumber-sucks-and-i-still-love-it\">Why Cucumber sucks and I still love it<\/a><\/li><li><a href=\"https:\/\/gist.github.com\/770894\">Why Steak (over Cucumber)<\/a><\/li><\/ul>\n\n\n\n<p>Previously we also use cucumber as tool for user stories.<br>Lately we found that our customers <strong>NEVER<\/strong> read cucumber features.<br>So do we need it anymore? Let&#8217;s check alternatives.<\/p>\n\n\n\n<p>As you probably know, cucumber use internally <a href=\"https:\/\/github.com\/jnicklas\/capybara\">Capybara<\/a> for steps implementation. And there is even more &#8211; latest version of Capybara comes with a built in DSL for creating descriptive acceptance tests!<\/p>\n\n\n\n<p>So we decided to switch to pure rspec+capybara testing.<br>We moved our features to <em>spec\/acceptance<\/em> directory.<br>Let&#8217;s look at rspec+capybara example.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RSpec+Capybara example<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">$ cat spec\/acceptance\/signup_feature_spec.rb<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">feature \"User signup\" do\n  background do\n    @user = Factory(:user, :email =&gt; 'jack@daniles.com', :password =&gt; 'qwerty')\n  end\n\n  scenario \"Signing in with correct credentials\" do\n    page.visit \"\/sessions\/new\"\n    page.fill_in \"email\", :with =&gt; \"jack@daniles.com\"\n    page.fill_in \"password\", :with =&gt; \"qwerty\"\n    page.click_button \"Login\"\n    page.should have_content(\"Welcome, jack@daniles.com!\")\n  end\n\n  scenario \"User tries to sign in with incorrect password\" do\n    page.visit \"\/sessions\/new\"\n    page.fill_in \"email\", :with =&gt; \"jack@daniles.com\"\n    page.fill_in \"password\", :with =&gt; \"bla\"\n    page.click_button \"Login\"\n    page.should have_content(\"Invalid credentials\")\n  end\nend<\/pre>\n\n\n\n<p>Thus approach has one big benefit:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Feature description and feature implementation are located together.<\/pre>\n\n\n\n<p>You don&#8217;t need anymore to jump between feature and step files to guess where is implementation for a step.<br>It&#8217;s nice but there are also two downsides.<\/p>\n\n\n\n<p>First downsides is that RSpec documentation output will be too poor and it&#8217;s not enough informative:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ rspec -fs -c spec\/acceptance\/signup_feature_spec.rb\n\nUser signup\n  Signing in with correct credentials\n  User tries to sign in with incorrect password\n\nFinished in 13.55 seconds\n2 examples, 0 failures<\/pre>\n\n\n\n<p>Second downside is that scenario does not have anymore exact boundary blocks or steps.<br>It makes harder to understand the scenario flow.<\/p>\n\n\n\n<p>Real user story often has big scenarios and we realized that cucumber steps were cool.<\/p>\n\n\n\n<p>There were two ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>switch back to cucumber<\/li><li>go further and invent<\/li><\/ul>\n\n\n\n<p><a href=\"https:\/\/railsware.com\/railswarians\/\">Railswarians<\/a> never go back :)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Our Solution<\/h3>\n\n\n\n<p>If you decided to switch from Cucumber to Capybara acceptance testing try <a href=\"https:\/\/github.com\/railsware\/rspec-example_steps\">rspec-example steps<\/a> gem.<\/p>\n\n\n\n<p>With this gem you may use <em>Given\/When\/Then<\/em> steps into rspec example!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RSpec+Capybara+Steps example<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">feature \"User signup\" do\n  background do\n    @user = Factory(:user, :email =&gt; 'jack@daniles.com', :password =&gt; 'qwerty')\n  end\n\n  Steps \"Signing in with correct credentials\" do\n    When \"I go to sign in page\" do\n      page.visit \"\/sessions\/new\"\n    end\n    And \"I fill in right email\" do\n      page.fill_in \"email\", :with =&gt; @user.email\n    end\n    And \"I fill in  right password\" do\n      page.fill_in \"password\", :with =&gt; \"qwerty\"\n    end\n    And \"I click login\" do\n      page.click_button \"Login\"\n    end\n    Then \"I should see greeting\" do\n      page.should have_content(\"Welcome, #{@user.email}!\")\n    end\n  end\n\n  Steps \"User tries to sign in with incorrect password\" do\n    When \"I go to sign in page\" do\n      page.visit \"\/sessions\/new\"\n    end\n    And \"I fill in right email\" do\n      page.fill_in \"email\", :with =&gt; @user.email\n    end\n    And \"I fill in wrong password\" do\n      page.fill_in \"password\", :with =&gt; \"bla\"\n    end\n    And \"I click login\" do\n      page.click_button \"Login\"\n    end\n    Then \"I should see error\" do\n      page.should have_content(\"Invalid credentials\")\n    end\n  end\nend<\/pre>\n\n\n\n<p>And documentation output will be:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ rspec -fs -c spec\/acceptance\/signup_feature_spec.rb<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">User signup\n  Signing in with correct credentials\n    When I go to sign in page\n    And I fill in right email\n    And I fill in right password\n    And I click login\" do\n    Then I should see greeting\n  User tries to sign in with incorrect password\n    When I go to sign in page\n    And I fill in right email\n    And I fill in wrong password\n    And I click login\n    Then I should see error\n\nFinished in 13.55 seconds\n2 examples, 0 failures<\/pre>\n\n\n\n<p>Now it&#8217;s much better. Isn&#8217;t it? :)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RSpec Example Steps features<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li>Does not hack RSpec Example. It only extends it.<\/li><li>Brings Given\/When\/Then\/And\/But steps support into rspec example block that allow you to better organize scenario<\/li><li>Adds shared_steps DSL<\/li><li>Adds ability to mark step as pending<\/li><li>Reports with color about passed\/pending\/failed step into documentation formating output<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Installation<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">$ gem install rspec-example_steps<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Usage<\/h3>\n\n\n\n<p>See <a href=\"https:\/\/github.com\/railsware\/rspec-example_steps\/blob\/master\/README.md\">README<\/a> for more details.<\/p>\n\n\n\n<p>Just add to <em>spec\/spec_helper.rb<\/em><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">require 'rspec\/example_steps'<\/pre>\n\n\n\n<p>And enjoy Given\/When\/Then step usage!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">References<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/railsware\/rspec-example_steps\">rspec-example_steps<\/a><\/li><li><a href=\"https:\/\/github.com\/cucumber\/cucumber\">cucumber<\/a><\/li><li><a href=\"https:\/\/github.com\/LRDesign\/rspec-steps\">rspec-steps<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Capybara with Given\/When\/Then steps in acceptance testing. Many of us use cucumber to write acceptance tests.We must to say it&#8217;s very nice tool that allows you to write features in English plain text.The main goal is provide interface that should be clear for Customer(non-programmer) and Developer. Cucumber example: Feature: User signup As a user I&#8230;<\/p>\n","protected":false},"author":19,"featured_media":9498,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Andriy Yanko"],"class_list":["post-1213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"https:\/\/railsware.com\/blog\/wp-content\/themes\/railsware\/vendors\/images\/article-thumbnail-default.jpg","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/1213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=1213"}],"version-history":[{"count":20,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/1213\/revisions"}],"predecessor-version":[{"id":13970,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/1213\/revisions\/13970"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/9498"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=1213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=1213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=1213"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=1213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}