In my previous post I took my first stab at Cucumber; first writing a failing Scenario, then getting it to pass, then writing a failing Spec and getting it to pass. The scenario in the previous post was overly simple, in fact I was able to complete it without writing any code at all. My goal this time is to continue my education with a slightly more realistic scenario.
One way to attack an application is in the same order it's used. In the case of a blog the author will need to add content before the site has any value, so that seems like a reasonable starting point.
# RAILS_ROOT/features/author_publish.feature
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post
Given I am on the post creation page
When I add a new post
Then I should see a page for the new post
The narrative for this feature was easy but deciding on how to approach the first scenario wasn't. In the end after browsing around the web and reading tons of material it was another post from
Ben Maybe called
"Imperative vs Declarative Scenarios in User Stories" that seemed to help me decide.
With that feature in place running cucumber:
./script/cucumber features/author_publish.feature
Produces the following:
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post # features/author_publish.feature:6
Given I am on the post creation page # features/step_definitions/webrat_steps.rb:6
Can't find mapping from "the post creation page" to a path. (RuntimeError)
/home/mgreenly/Projects/blog/features/support/paths.rb:11:in `/^I am on (.+)$/'
features/author_publish.feature:7:in `Given I am on the post creation page'
When I add a new post # features/author_publish.feature:8
Then I should see a page for the new post # features/author_publish.feature:9
1 scenario
1 failed step
2 undefined steps
You can implement step definitions for missing steps with these snippets:
When /^I add a new post$/ do
pending
end
Then /^I should see a page for the new post$/ do
pending
end
The problem here is cucumber doesn't know what to map the phrase 'the post creation page' to. This can be fixed by adding the following code to the navigation helper.
def path_to(page_name)
case page_name
when /the homepage/
root_path
when /the post creation page/
post_path("new")
else
raise "Can't find mapping from \"#{page_name}\" to a path."
end
end
Now we run cucumber again:
./script/cucumber features/author_publish.feature
And it produces the following:
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post # features/author_publish.feature:6
Given I am on the post creation page # features/step_definitions/webrat_steps.rb:6
undefined method `post_path' for # (NoMethodError)
/home/mgreenly/Projects/blog/features/support/paths.rb:9:in `/^I am on (.+)$/'
features/author_publish.feature:7:in `Given I am on the post creation page'
When I add a new post # features/author_publish.feature:8
Then I should see a page for the new post # features/author_publish.feature:9
1 scenario
1 failed step
2 undefined steps
You can implement step definitions for missing steps with these snippets:
When /^I add a new post$/ do
pending
end
Then /^I should see a page for the new post$/ do
pending
end
Now it's complaining that it can't find a mapping for the Post resource. That makes sense since in my previous round I only created a controller. Instead of laboring through the process to create the Post model why not cheat and use the built in generator.
./script/generate rspec_scaffold -f Post title:string body:text
Obvious, going this route means I've broken my previously completed feature, so out of curiosity lets check it out.
Running cucumber on the original feature:
./script/cucumber features/reader_browse.feature
Produces the following:
Feature: browsing
As a reader
I want to browse the site
So that I can read it's content
Scenario: visit the homepage # features/reader_browse.feature:6
When I go to the homepage # features/step_definitions/webrat_steps.rb:10
Then I should see "Hello world!" # features/step_definitions/webrat_steps.rb:93
expected the following element's content to include "Hello world!":
Posts: index
Listing posts
Title
Body
New post
(Spec::Expectations::ExpectationNotMetError)
features/reader_browse.feature:8:in `Then I should see "Hello world!"'
1 scenario
1 failed step
1 passed step
Broken as expected. The problem is that the index page no longer has the "Hello world!" text on it. No problem we'll fix that later, for now lets keep going on the new feature.
When I run cucumber now:
./script/cucumber features/author_publish.feature
I get:
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post # features/author_publish.feature:6
Given I am on the post creation page # features/step_definitions/webrat_steps.rb:6
When I add a new post # features/author_publish.feature:8
Then I should see a page for the new post # features/author_publish.feature:9
1 scenario
2 undefined steps
1 passed step
You can implement step definitions for missing steps with these snippets:
When /^I add a new post$/ do
pending
end
Then /^I should see a page for the new post$/ do
pending
end
So now the it's obviously finding the 'the post creation page' but the remaining When/Then are still pending.
So now I add the following code:
When /^I add a new post$/ do
fill_in "Title" , :with => "Some Title"
click_button "Create"
end
Then I run cucumber:
./script/cucumber features/author_publish.feature
And get the following:
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post # features/author_publish.feature:6
Given I am on the post creation page # features/step_definitions/webrat_steps.rb:6
When I add a new post # features/step_definitions/posts_steps.rb:1
Then I should see a page for the new post # features/author_publish.feature:9
1 scenario
1 undefined step
2 passed steps
You can implement step definitions for missing steps with these snippets:
Then /^I should see a page for the new post$/ do
pending
end
Now I just need to satisfy the 'Then'
Then /^I should see a page for the new post$/ do
response.should contain("Post was successfully created")
end
Then I run cucumber and get the following:
Feature: author publish
As an author
I want to publish a post
So that it can be read
Scenario: publish a post # features/author_publish.feature:6
Given I am on the post creation page # features/step_definitions/webrat_steps.rb:6
When I add a new post # features/step_definitions/publish_steps.rb:1
Then I should see a page for the new post # features/step_definitions/publish_steps.rb:6
1 scenario
3 passed steps
Everything works, except the feature I broke, but I'll pick up there in the next post.