LoginSignup
7
10

More than 5 years have passed since last update.

E2EテストをPageObjectパターンで実装する

Posted at

E2Eテスト実装のベストプラクティスとされているPageObjectパターンを試してみました。

テストケース

Djangoの管理画面からユーザ作成を行うテストを実装しました。
流れは次のとおりです。

  1. ログイン画面でユーザ名、パスワードを入力して[ログイン]をクリック
  2. 管理画面でユーザーの[+追加]をクリック
  3. ユーザ管理画面でユーザ名、パスワード、パスワードの確認を入力して[保存]をクリック
  4. ユーザ管理画面にユーザ作成完了のメッセージが表示されていることをテスト

PageObjectの実装

PageObjectはページ単位で作成するので、今回のケースだと次のPageObjectが必要になります。

  • LoginPage
    • ログイン画面
  • AdminPage
    • ログイン後に表示される管理画面
  • AddUserPage
    • 管理画面でユーザーの[+追加]をクリックした後に表示されるユーザ追加画面
  • UserPage
    • ユーザ追加完了後に表示される画面

ページ内で実行する操作をメソッドとして実装しますが、フォームへの入力、クリックなどの細かい単位ではなく、ある程度まとまったタスクをメソッドにします。
具体的には次のようにしました。

  • LoginPage
    • loginメソッド
      • ユーザ名、パスワードを入力して[ログイン]をクリック
  • AdminPage
    • go_to_add_user_pageメソッド
      • ユーザーの[+追加]をクリック
  • AddUserPage
    • add_userメソッド
      • ユーザ名、パスワード、パスワードの確認を入力して[保存]をクリック
  • UserPage
    • 今回は特に操作しないのでメソッドはなし

コード

実装したコードは次のとおりです。以下のリポジトリにも同じコードがあります。
https://github.com/shiimaxx/page-object-pattern-example

ログインページ

login.py
from pages.admin import AdminPage


class LoginPage(object):

    def __init__(self, driver):
        self.driver = driver

    def login(self, username, password):
        login_form = self.driver.find_element_by_id('login-form')
        username_ = login_form.find_element_by_name('username')
        password_ = login_form.find_element_by_name('password')
        button = login_form.find_element_by_css_selector('input[value="ログイン"]')
        username_.send_keys(username)
        password_.send_keys(password)
        button.click()
        return AdminPage(self.driver)

管理ページ

admin.py
from pages.user import AddUserPage


class AdminPage():

    def __init__(self, driver):
        self.driver = driver

    def go_to_add_user_page(self):
        self.driver.find_element_by_css_selector('a[href="/admin/auth/user/add/"]').click()
        return AddUserPage(self.driver)

ユーザ管理ページ

user.py
class AddUserPage(object):

    def __init__(self, driver):
        self.driver = driver

    def add_user(self, username, password):
        user_form = self.driver.find_element_by_id('user_form')
        username_ = user_form.find_element_by_name('username')
        password1 = user_form.find_element_by_name('password1')
        password2 = user_form.find_element_by_name('password2')
        button = user_form.find_element_by_name('_save')
        username_.send_keys(username)
        password1.send_keys(password)
        password2.send_keys(password)
        button.click()
        return UserPage(self.driver)


class UserPage(object):

    def __init__(self, driver):
        self.driver = driver

テスト

test_django_admin.py
import unittest

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

from pages.login import LoginPage


class TestDjangoAdmin(unittest.TestCase):

    def setUp(self):
        options = Options()
        options.binary_location = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(chrome_options=options)
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.set_page_load_timeout(30)
        self.driver.set_window_size(1920, 1080)

    def test_add_user(self):
        self.driver.get('http://127.0.0.1:8000/admin')
        login_page = LoginPage(self.driver)
        admin_page = login_page.login('admin', 'p@ssword')
        add_user_page = admin_page.go_to_add_user_page()
        user_page = add_user_page.add_user('testuser', 'dummy_p@ssword')
        self.assertIn('testuser</a>" を追加しました。続けて編集できます。</li>', user_page.driver.page_source)

    def tearDown(self):
        self.driver.close()

まとめ

今回は1つのテストケースしか実装しなかったのでPageObjectパターンの恩恵はそこまでないかもしれませんが、テストを運用していくことを想定すると、テストケースが読みやすかったり、PageObjectやメソッドの再利用によってテストケースが追加しやすくなっていたりなど、保守性は上がっている状態だと思います。

参考文献

7
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10