Friday, September 11, 2009

Holy Crap

‹prev | My Chain | next›

With the recipe update feature complete (or at least effectively pushed off for completion another day), I am extremely close to being feature complete:
cstrom@jaynestown:~/repos/eee-code$ cucumber features/
...
37 scenarios (2 undefined, 1 pending, 34 passed)
334 steps (9 skipped, 7 undefined, 1 pending, 317 passed)
0m39.874s
To be sure, there is much code clean-up that can be done and some optimization (caching would be a very good thing), but wow, only 2 undefined scenarios?

Maybe I can cut that to one tonight...

The last remaining feature is alternate recipe preparation (Robin's family has many ways to make tomato sauce). The feature in Cucumber format:
Feature: Alternate preparations for recipes

As a user curious about a recipe
I want to see a list of similar recipes
So that I can find a recipe that matches my tastes or ingredients on hand

Scenario: No alternate preparation

Given a "pancake" recipe with "buttermilk"
And no other recipes
When I view the recipe
Then I should see no alternate preparations

Scenario: Alternate preparation

Given a "Hearty Pancake" recipe with "wheat germ"
And a "Buttermilk Pancake" recipe with "buttermilk"
And a "Pancake" recipe with "chocolate chips"
When the three pancake recipes are alternate preparations of each other
And I visit the "Hearty Pancake" recipe
Then I should see a link to the "Buttermilk Pancake" recipe
And I should see a link to the "Pancake" recipe
And I should not see a link to the "Hearty Pancake" recipe
When I click the "Buttermilk Pancake" link
Then I should see a link to the "Hearty Pancake" recipe
And I should see a link to the "Pancake" recipe
And I should not see a link to the "Buttermilk Pancake" recipe
Sweet! That first scenario is a happy path description of how recipes behave normally (when no alternates exist). Even better, the second step is a no-op and can be defined as:
Given /^no other recipes$/ do
# nop
end
Thanks to previously defined steps, there is but one step remaining:



On the legacy site, the alternate preparations look like:



So the absence of an alternate preparation can be defined as:
Then /^I should see no alternate preparations$/ do
response.should_not contain('Alternate Preparations')
end
Since I have not created the feature yet, this passes right away:



That may seem like a useless scenario. The point is to ensure that nothing changes for non-alternate preparation recipes when I implement the feature.

Just like that, I am down to one remaining scenario. At first glance, the step definitions in that last scenario are almost done:



I say "at first glance" because there is a little too much bold in the blue steps. I want to verify that the text inside the quotes of those step are links on the pages. The extra bold is telling me that the step is going to look for everything bold.

I cannot simply define another, more specific step definition. This is Cucumber, not CSS. Instead I need to change the old step definition to no longer match:
Then /^I should see a link to (.+)$/ do |date|
response.should have_selector("a", :content => date)
end
So, instead of the match anything (.) RexExp, I match anything but a quote:
Then /^I should see a link to ([^\"]+)$/ do |date|
response.should have_selector("a", :content => date)
end
Since that step no longer matches the steps in the current scenario (because they have quotes), I can define those steps as:
Then /^I should see a link to the "([^\"]*)" recipe$/ do |title|
response.should have_selector("a", :content => title)
end
With that, I have good bold:



I do not normally define steps before doing inside work (preferring to do them afterwards to verify the inside work), but those steps were obviously wrong. While I am on a roll, I might as well finish the last two steps off. Making use of the instance variable lookup from the updated recipes features, I can define the visit the recipe step as:
When /^I visit the "Hearty Pancake" recipe$/ do
visit "/recipes/#{@permalink_identified_by['wheat germ']}"
end
The last undefined cucumber step in my entire application(!) describes the alternate preparations document. On the really old, XML document based legacy site (the one that pre-dates the Rails legacy site) the alternates preparation documents were a simple list of the recipes:
<recipes>
<recipe year="2002" month="08" day="12" label="sauce"/>
<recipe year="2003" month="01" day="17" label="sausage_pasta"/>
<recipe year="2003" month="02" day="13" label="pasta"/>
<recipe year="2003" month="02" day="16" label="sauce"/>
<recipe year="2003" month="04" day="07" label="cavatelli"/>
<recipe year="2004" month="02" day="04" label="squid"/>
<recipe year="2004" month="04" day="26" label="sauce"/>
<recipe year="2006" month="02" day="14" label="sauce"/>
</recipes>
To do the same on the CouchDB based site, I can define the alternate preparations document as:
Given /^the three pancake recipes are alternate preparations of each other$/ do
alternates = {
:type => "Alternate",
:name => "pancakes",
:recipes => [
@permalink_identified_by['wheat germ'],
@permalink_identified_by['buttermilk'],
@permalink_identified_by['chocolate chips']
]
}

RestClient.put "#{@@db}/pancake_alternates",
alternates.to_json,
:content_type => 'application/json'
end
With that I have all of my steps defined:
cstrom@jaynestown:~/repos/eee-code$ cucumber   features/recipe_alternate_preparations.feature:14
Sinatra::Test is deprecated; use Rack::Test instead.
Feature: Alternate preparations for recipes

As a user curious about a recipe
I want to see a list of similar recipes
So that I can find a recipe that matches my tastes or ingredients on hand

Scenario: Alternate preparation
Given a "Hearty Pancake" recipe with "wheat germ"
And a "Buttermilk Pancake" recipe with "buttermilk"
And a "Pancake" recipe with "chocolate chips"
When the three pancake recipes are alternate preparations of each other
And I visit the "Hearty Pancake" recipe
Then I should see a link to the "Buttermilk Pancake" recipe
expected following output to contain a <a>Buttermilk Pancake</a> tag:

...
And I should see a link to the "Pancake" recipe
And I should not see a link to the "Hearty Pancake" recipe
When I click the "Buttermilk Pancake" link
Then I should see a link to the "Hearty Pancake" recipe
And I should see a link to the "Pancake" recipe
And I should not see a link to the "Buttermilk Pancake" recipe

Failing Scenarios:
cucumber features/recipe_alternate_preparations.feature:14 # Scenario: Alternate preparation

1 scenario (1 failed)
12 steps (1 failed, 6 skipped, 5 passed)
0m0.675s
The steps are defined, but not passing because I still need to actually write the code to implement the feature. I will pick that up tomorrow at which point, the site should be (dare I say it?) feature complete!

No comments:

Post a Comment