Seleniumコードサンプル#3 ページオブジェクトパターン
自動テストのための学習のため、Seleniumコードサンプル(ページオブジェクトパターン)を実施してみます。
以前、読んだpython用の書籍だとすでに試せるサイトが大幅に変わってしまったので、
自分でHTMLファイルを作成して、疑似的に下記の構成を確認しています。
今回は、ページオブジェクトデザインパターンを利用したテストする仕組みを実装してみました。
[画面イメージ]
今回は下記の内容を試してみました。
【項目】
・データ駆動テスト
・ページオブジェクトデザインパターン
構成はこんな感じ。
書籍もそんなに読み込んでいないのですが…、要はテストケースとテスト対象(画面)の操作を切り分けて、
ベースとなる処理をそれぞれで実装してあげる…というようなものです。
これにより、下記のような効果が期待できます。
- テスト対象ページが開発者によって変更されたときの変更を最小限に抑えるのに役立つ高レベルの抽象化を作成します。したがって、ページオブジェクトのみを変更し、呼び出しテスト(テストスイートやテストケース)は影響を受けない。
- 複数のテストケースで共有できる再利用可能なコードの作成できる。
- テストはより読みやすく、柔軟性があり、保守が容易になる。
[ basepage.py]
from abc import abstractmethod class BasePage(object): """ All page objects inherit from this """ def __init__(self, driver): self.driver = driver
[samplepage.py]
from basepage import BasePage import time from selenium import webdriver from selenium.webdriver.support.ui import Select class SamplePage(BasePage): def __init__(self, driver): super(SamplePage, self).__init__(driver) def submit_data(self, username, password, month): # input ID/PASS and push submit botton id = self.driver.find_element_by_name("Username") id.send_keys(str(username)) password = self.driver.find_element_by_name("Password") password.send_keys(str(password)) dropdownlist = self.driver.find_element_by_name("Month") month_select_element = Select(dropdownlist) month_select_element.select_by_value(str(month)) time.sleep(2) self.driver.find_element_by_name("Submit").click()
[basetestcase.py](Testcase)
import unittest from selenium import webdriver from selenium.webdriver.support.ui import Select class BaseTestCase(unittest.TestCase): def setUp(self): # create a new Chrome session self.driver = webdriver.Chrome(executable_path=r'C:/tmp/selenium/chromedriver_win32/chromedriver.exe') self.driver.implicitly_wait(30) self.driver.maximize_window() # navigate to page self.driver.get("file:///C:/cygwin64/home/XXX/selenium/pageobjectpattern/01_sample.html") def tearDown(self): # close the browser window self.driver.quit()
[sampletestcase.py]
import unittest from samplepage import SamplePage from basetestcase import BaseTestCase from ddt import ddt, data, unpack @ddt class SamplePageTestCase(BaseTestCase): @data(("odan","odanpass","feb"),("tomohiro","tomohiropass","jul")) @unpack def test_samplehtml(self, username, password, month): sample_page = SamplePage(self.driver) sample_page.submit_data(username, password, month) # true self.assertEqual(10, 10) if __name__ == '__main__': unittest.main(verbosity=2)
[sample.html]
<html> <body> <!-- 入力フォーム --> <form id="loginForm"> <label>Enter Username: </label> <input type="text" name="Username"/> <label>Enter Password: </label> <input type="password" name="Password"/> <!-- ドロップダウンリスト --> <select name="Month"> <option value="jan">1月</option> <option value="feb">2月</option> <option value="mar">3月</option> <option value="apr">4月</option> <option value="may">5月</option> <option value="jun">6月</option> <option value="jul">7月</option> <option value="aug">8月</option> <option value="sep">9月</option> <option value="oct">10月</option> <option value="nov">11月</option> <option value="dec">12月</option> </select> <!-- ボタン --> <input type="submit" name="Submit"/> </form> <a href="forgotPassword.html">Forgot Password ?</a> </body> </html>
実行すると下記のような出力になります。
$ python samplepagetestcase.py test_samplehtml_1___odan____odanpass____feb__ (__main__.SamplePageTestCase) ... ok test_samplehtml_2___tomohiro____tomohiropass____jul__ (__main__.SamplePageTestCase) ... ok ---------------------------------------------------------------------- Ran 2 tests in 26.403s OK
【まとめ】
ページオブジェクトとを利用したテストを作成することができました。
今回は複数のページを利用していないので全く利点が享受できていない感じですが、実際にはテストケースとページの具体的な操作を切り分けることができるので、画面の操作仕様が変わった際にページオブジェクトを変更、テスト仕様が変わった時にテストケースを変更するなど関心事を分けて作業できるのが利点なのだろうなと感じました。読みやすいのかどうかは、今回はシンプルすぎて確認できませんでした…。
次回は、ページオブジェクトパターンを複数ページのサンプル、もしくは実機を使ったモバイルテストを試してみたいと思います。