Writing our first feature

Let’s create the our first feature. Create a new file named basic.feature under the folder features/ with the following content.

Feature: Basic
  Scenario: In the homepage
    Given I am on homepage
    Then I should see "Welcome"

Now we can run rake cucumber to test the scenario.

And here is the result.

Feature: Basic

  Scenario: In the homepage     # features/basic.feature:2
    Given I am on homepage      # features/basic.feature:3
      Undefined step: "I am on homepage" (Cucumber::Undefined)
      features/basic.feature:3:in `Given I am on homepage'
    Then I should see "Welcome" # features/basic.feature:4
      Undefined step: "I should see "Welcome"" (Cucumber::Undefined)
      features/basic.feature:4:in `Then I should see "Welcome"'

1 scenario (1 undefined)
2 steps (2 undefined)
0m0.398s

You can implement step definitions for undefined steps with these snippets:

Given(/^I am on homepage$/) do
  pending # express the regexp above with the code you wish you had
end

Then(/^I should see "(.*?)"$/) do |arg1|
  pending # express the regexp above with the code you wish you had
end

The cucumber is cleaver enough to find all non-handle English sentense and tell us how to handle them. And it will replace double-quoted string into variable. And rerember, the steps are just regular expression. Feel free to change it to whatever that works for you.

So the next step is to create step files to describe how to deal with the feature sentences.

Create a new file named basic_steps.rb under features/step_definitions folder.

Then we copy the cucumber suggestions into the step file.

Given(/^I am on homepage$/) do
  pending # express the regexp above with the code you wish you had
end

Then(/^I should see "(.*?)"$/) do |arg1|
  pending # express the regexp above with the code you wish you had
end

When we run the rake cucumber command now, we see the step is reconized and in pending state.

Feature: Basic

  Scenario: In the homepage     # features/basic.feature:2
    Given I am on homepage      # features/step_definitions/basic_steps.rb:1
      TODO (Cucumber::Pending)
      ./features/step_definitions/basic_steps.rb:2:in `/^I am on homepage$/'
      features/basic.feature:3:in `Given I am on homepage'
    Then I should see "Welcome" # features/step_definitions/basic_steps.rb:5

1 scenario (1 pending)
2 steps (1 skipped, 1 pending)
0m0.439s

Let’s implement the first pending step with the following code.

1Given(/^I am on homepage$/) do
2  visit root_path
3end

Now we get a fail when running rake cucumber.

Feature: Basic

  Scenario: In the homepage     # features/basic.feature:2
    Given I am on homepage      # features/step_definitions/basic_steps.rb:1
      undefined local variable or method `root_path' for #<Cucumber::Rails::World:0x007f8b6170afc8> (NameError)
      ./features/step_definitions/basic_steps.rb:2:in `/^I am on homepage$/'
      features/basic.feature:3:in `Given I am on homepage'
    Then I should see "Welcome" # features/step_definitions/basic_steps.rb:5

Failing Scenarios:
cucumber features/basic.feature:2 # Scenario: In the homepage

1 scenario (1 failed)
2 steps (1 failed, 1 skipped)
0m0.322s

It is because we haven’t modify our root page yet.

Now turn to the code ane create a pages controller with an index action.

$ rails generate controller pages index

And we add the root_path in the routes.rb file.

1Gallery::Application.routes.draw do
2  root to:'pages#index'
3end

Finally we remove the public/index.html file.

Running rake cucumber now will pass the first step “Given I am on homepage”, and leave the second one “Then I should see "Welcome"”

So the next step is to implement the remaining pending steps.

1Then(/^I should see "(.*?)"$/) do |wording|
2  page.should have_content wording
3end

And we get the error “expected to find text "Welcome"” after running the rake cucumber again.

Feature: Basic

  Scenario: In the homepage     # features/basic.feature:2
    Given I am on homepage      # features/step_definitions/basic_steps.rb:1
    Then I should see "Welcome" # features/step_definitions/basic_steps.rb:5
      expected to find text "Welcome" in "Pages#index Find me in app/views/pages/index.html.erb" (RSpec::Expectations::ExpectationNotMetError)
      ./features/step_definitions/basic_steps.rb:6:in `/^I should see "(.*?)"$/'
      features/basic.feature:4:in `Then I should see "Welcome"'

Failing Scenarios:
cucumber features/basic.feature:2 # Scenario: In the homepage

1 scenario (1 failed)
2 steps (1 failed, 1 passed)
0m0.564s

So let’s add the “Welcome” to the root page. Then running the rake cucumber again will give us all passes.

Feature: Basic

  Scenario: In the homepage     # features/basic.feature:2
    Given I am on homepage      # features/step_definitions/basic_steps.rb:1
    Then I should see "Welcome" # features/step_definitions/basic_steps.rb:5

1 scenario (1 passed)
2 steps (2 passed)
0m0.520s

The idea of test-driven is to write the test first by describing how the work should work. Then obviously it is going to fail. And we observe what make the test fails and write code to make it just work. At last, we refractor the code to make it work in more generic way. Then we go to the next pending/failing case.

What’s next? We’re going to take a look at “Writing the user authentication component”.

overlaied image when clicked on thumbnail

Makzan | Ruby on rails 101 | Table of Content