如何去創(chuàng)建一個(gè)Page Object,下面有一些建議:
盡量給每一個(gè)page頁面創(chuàng)建一個(gè)Page Object
如果一個(gè)頁面包含過多的業(yè)務(wù)邏輯,你可以考慮將它創(chuàng)建為多個(gè)Page Object
把element的詳細(xì)處理都封裝起來
對于測試代碼里,永遠(yuǎn)不要直接去操作element對象,或者操作browser。
如果使用Rspec或者Cucumber,在define_step里,不要有直接操作的代碼
Page Object的目標(biāo)是當(dāng)頁面發(fā)生變化是,你不需要去修改測試代碼,而是修改后面的object層
不要在Page Ojbect中包含Assertion,斷言應(yīng)該仍在在代碼層實(shí)現(xiàn)
我們來討論一個(gè)實(shí)例:
browser = Watir::Browser.new
browser.goto "http://example.com/login"
browser.text_field(:name => "user").set "Mom"
browser.text_field(:name => "pass").set "s3cr3t"
browser.button(:id => "login").click
Watir::Wait.until { browser.title == "Your Profile" }
browser.div(:id => "logged-in").should exist
這是一個(gè)簡單的例子,完全按照workflow去操作一個(gè)個(gè)element對象
如果將其Page Object化,那么看其起來是這個(gè)樣子的:
site = Site.new(Watir::Browser.new)
login_page = site.login_page.open
user_page = login_page.login_as "Mom", "s3cr3t"
user_page.should be_logged_in
請注意一下對應(yīng)關(guān)系
為了實(shí)現(xiàn)Page Obejcts化,我們需要將詳細(xì)的步驟,封裝起來:
class BrowserContainer
def initialize(browser)
@browser = browser
end
end
class Site < BrowserContainer
def login_page
@login_page = LoginPage.new(@browser)
end
def user_page
@user_page = UserPage.new(@browser)
end
def close
@browser.close
end
end # Site
class LoginPage < BrowserContainer
URL = "http://example.com/login"
def open
@browser.goto URL
self
end
def login_as(user, pass)
user_field.set user
password_field.set pass
login_button.click
next_page = UserPage.new(@browser)
Watir::Wait.until { next_page.loaded? }
next_page
end
private
def user_field
@browser.text_field(:name => "user")
end
def password_field
@browser.text_field(:name => "pass")
end
def login_button
@browser.button(:id => "login")
end
end # LoginPage
class UserPage < BrowserContainer
def logged_in?
logged_in_element.exists?
end
def loaded?
@browser.title == "Your Profile"
end
private
def logged_in_element
@browser.div(:id => "logged-in")
end
end
從上面代碼可以看出,Page Objects化之后,我們的測試代碼都是按照封裝好的去書寫,例如,將手工測試用例map到自動化測試步驟(Cucumber),在代碼更迭之后,我們只需要去修改后面封裝的對應(yīng)代碼,從而避免如下的問題發(fā)生:
1. 漏掉一部分代碼沒有更新
2. 更新錯(cuò)誤
3. 打亂了原有的代碼結(jié)構(gòu)
4. 重復(fù)代碼過多
5. 定位錯(cuò)誤困難
當(dāng)完成Page Object化之后,跟其他的工具集成很簡單了,例如,在cucumber中我們可以在初始化測試環(huán)境中加入一段代碼:
require "watir-webdriver"
require "/path/to/site"
module SiteHelper
def site
@site ||= (
Site.new(Watir::Browser.new(:firefox))
)
end
end
World(SiteHelper)
這樣,得到一個(gè)更加合理優(yōu)化的代碼結(jié)構(gòu)。
而且匹配過程變更加清晰明了:
Given /I have successfully logged in/ do
login_page = site.login_page.open
user_page = login_page.login_as "Mom", "s3cr3t"
user_page.should be_logged_in
end