概要
画面操作とテストシナリオが疎結合にできるPageObjectデザインパターンを試したかったので、検索ワードにヒットする商品を自動購入するAmazonの自動購入処理を書きました。
参考ページをCapybaraに移植したものになります。
PageObjectデザインパターンとは
公式によるとPageObjectデザインパターンとは、以下だそうです。
・The public methods represent the services that the page offers(publicメソッドは、ページが提供するサービスを表す)
・Try not to expose the the internals of the page (ページの内部を公開しないこと)
・Generally don’t make assertions (原則としてassertionを行わないこと)
・Methods return other PageObjects (メソッドは他のPageObjectsを返す)
・Need not represent an entire page (ページ全体を表す必要はない)
・Different results for the same action are modelled as different as different methods (同じアクションに対して異なる結果となる場合には異なるメソッドとしてモデル化する)
PageObjectデザインパターンを利用して画面変更に強いUIテストを作成する│ソフトウェアテストラボ
仕様
Amazonのホームから、任意の検索ワードで検索して、商品をカゴに入れて代引きで購入します。
実装
require "capybara"
require "selenium-webdriver"
Capybara.current_driver = :selenium
Capybara.configure do |config|
config.run_server = false
config.app_host = "http://www.amazon.co.jp"
end
id = "example@exmaple.com"
pass = "password"
module Amazon
class Page
include Capybara::DSL
end
class HomePage < Page
def goHome
visit "/"
self
end
def searchItem word
fill_in "field-keywords" , with: word
click_on '検索'
SearchResultPage.new
end
end
class SearchResultPage < Page
def choiceItem num=0
all(".s-item-container")[num]
.find(".a-link-normal.s-access-detail-page.a-text-normal").click
current_window.close
switch_to_window windows[0]
ItemDetailPage.new
end
end
class ItemDetailPage < Page
def addToShoppingCart
sleep 2
all("[id='add-to-cart-button']")[0].click
RecommendPage.new
end
end
class RecommendPage < Page
def goCart
find("#hlb-ptc-btn-native").click
LoginPage.new
end
end
class LoginPage < Page
def login id, password
fill_in 'email' , with: id
fill_in 'password' , with: password
find("#signInSubmit-input").click
DeliveryPage.new
end
end
class DeliveryPage < Page
def choiceAddress num=0
all("a.a-declarative.a-button-text")[num].click
sleep 3
DeliveryOptionPage.new
end
end
class DeliveryOptionPage < Page
def goNextPage
first(".a-button-text").click
sleep 3
PaymentPage.new
end
end
class PaymentPage < Page
def goNextPage
first(".a-button-text").click
sleep 2
ConfirmationPage.new
end
def changeOption option
if option == :cod
first("div.radio-col.spacing-right-small > input[value='cashOnDeliveryCash']").set(true)
end
self
end
end
class ConfirmationPage < Page
def decision
save_screenshot('screenshot.png')
first(".a-button-text.place-your-order-button").click
end
end
end
Amazon::HomePage.new
.goHome
.searchItem("Selenium")
.choiceItem
.addToShoppingCart
.goCart
.login(id, pass)
.choiceAddress(0)
.goNextPage
.changeOption(:cod)
.goNextPage
.decision
まとめ
スクレイピングするのが好きなのですが、ページオブジェクトパターンは返り値としてページオブジェクトを使うのでルールに準拠するとスクレイピングには使えないですね。
ほどよく、UI操作とシナリオを分割してコード書きたいです。
参考文献
- PageObjectデザインパターンを利用して画面変更に強いUIテストを作成する│ソフトウェアテストラボ|アプリテスト|スマートフォンテスト|株式会社シフト
- PageObjects - selenium - The Page Object pattern represents the screens of your web app as a series of objects - Browser automation framework - Google Project Hosting
- Test Design Considerations — Selenium Documentation
注意
Kindleの商品の場合、カートに入れるボタンが無いなど、一部動かない場合があります。
サンプルということで。
住所はすでに登録されているものとして、進めています。