Static Types Don't Fail Me Now
May 12th 2010I’m really excited about using Cucumber. There has been a desire to get to that level of BDD-ish style tests ever since I first saw how readable they were. We’re ready to make that next step. Let’s pretend we have the following set of pages.
Pretty straight forward. We should be able to write a pretty simple Cucumber feature.
Feature: Add Foos
In order to keep track of foos
As a person who enters foos
I want to be able to add a foo
Scenario: Adding a foo without searching
Given I view the welcome page
When I click the Add New Foo button
Then I'm taken to the Add Foo page
Scenario: Adding a Foo
Given I've searched for a foo that doesn't exist
When I click the "save" ...that should say "Add"
Then I'm taken to the Add Foo page
Simple enough. I’m not going to walk you through how to write the steps for that. I’m more interested in how you organize the pages into page modules inside a static language. In Ruby you could do something like
class WelcomePage
def intialize(browser)
@browser = browser
self.goto
end
def goto
end
def addFoo
@browser.click '#add'
AddFooPage.new(@browser)
end
def searchForFoo(query)
@browser.type(query).into('#t') # made up syntax
@browser.click '#b'
SearchResultsPage.new(@browser)
end
end
class SearchResultsPaage
def initialize(browser)
@browser = browser
end
def addFoo
@browser.click '#add'
end
end
That isn’t WatiR. It’s totally made up. I’m a Ruby Newby too so told shoot me for any syntax errors.
You can drive it with something like this.
Given /I view the welcome page/ do @page = WelcomePage.new(browser) end Given /I search for (.*)/ do |q| @page = page.searchFor(q) end Given /I click on the add button/ do @page = page.addFoo() end
Pretty straight forward huh? Well how I do that in C#? All of those Navigate methods will either return a specific page type or a base type that will make it impossible to call the subsequent specific steps.
public class WelcomePage{
public SearchResultsPage SearchFor(query){
_browser.Type(query).into('#q');
_browser.Click('#btn');
return new SearchResultsPage(_browser);
}
}
public class SearchResultsPage{
public AddFooPage AddFoo(){
return new AddFooPage(_browser);
}
}
Then drive it with this.
var welcome = new WelcomePage(_browser);
var results = welcome.SearchFor('bar');
var add = results.AddFoo();
Doesn’t that feel messy? Luckily, I think a feature of .Net 4.0 might save the day!
dynamic page = new WelcomePage(_browser);
page = page.SearchFor('bar');
page = page.AddFoo();
Three cheers for dynamic!
