
Appiumのテストスクリプトを整理整頓する
前回の記事でiOSのモバイルアプリのテストを自動化できるようにAppiumの学習を進めてきました。
今回はテストスクリプトも長くなってきたのでファイルの整理整頓をしていきたいと思います
1. 整理整頓する目的と利点
Xcodeのプロジェクトファイルも整理整頓されていると後から見た時や他の開発者が見たときにどのファイルで何をしているのか分かりやすいですよね
もちろんテストのスクリプトにもその観点がありますが、
特にテストの観点では以下の観点でファイルを分けるのがよさそうです!
認証情報の保護
試験の性質的にログインに必要なメールアドレスやパスワード、または入力するテキストなどにもセンシティブな情報があったりしてそのような情報は別ファイルで管理することで、Githubのリポジトリなどチームで資材を管理する場所に公開することを防ぐことができます
テスト実行時間の短縮
一つのアプリの機能を実行していこうとすると結構長い時間がかかることが考えられます。例えばログインして、ホームスクリーンでいくつかの操作をして出てくる画面のテストをしたいとき、毎回ログインからテストを実行しているとテストにとても時間がかかってしまいます。
2. ファイル構成
以下のようにフォルダー・ファイルを構成します
ファイル名が数字だとPythonが他ファイルにインポートするときに認識できないため数字を冒頭にしないように気をつけます
AppiumTests/
│── pages/
│ ├── __init__.py
│ ├── page_01_login.py
│ ├── page_02_home.py
│ ├── page_99_base.py
│
│── tests/
│ ├── __init__.py
│ ├── test_01_login.py
│ ├── test_02_home.py
│
│── utils/
│ ├── __init__.py
│ ├── driver_setup.py
│
│── __init__.py
│── config.py
│── test_runner.py
pages
各テストスクリプトに対して具体的にどのようなボタンを押すのか、どのようなテキストを入力するのかを定義します
tests
実際のテストの流れを定義します。pagesのファイルで具体的な内容は定義されるので、テストの順番やページを読み込む待ち時間を記載することがメインになります
utils
テストする端末やアプリへのパスなどを定義します
__init__.py
このファイルはPythonがフォルダーをモジュール (テストに必要なファイル)として認識するために必要になります。内容は適当なコメントだけで問題ありません
config.py
ログインに必要なメールアドレスやパスワードなどGithubのリポジトリなどで共有したくない情報を管理します
test_runner.py
testファイルにあるファイルを全て一括して実行するためのファイルです
3. 各ファイルの内容例
pages
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.common.by import By
from pages.page_99_base import BasePage
import config
class LoginPage(BasePage):
GOOGLE_LOGIN_BUTTON = (AppiumBy.ACCESSIBILITY_ID, "GIDSignInButton")
def click_google_login(self):
self.click(*self.GOOGLE_LOGIN_BUTTON)
def click_continue_ios_alert(self):
self.driver.switch_to.alert.accept()
# configファイルのアカウント名とメールアドレスを使う
def click_existing_google_account(self):
self.click(By.XPATH, f'//XCUIElementTypeLink[@name="{config.GOOGLE_ACCOUNT_NAME}"]')
def click_continue_login_button(self):
self.click(AppiumBy.ACCESSIBILITY_ID, 'Continue')
tests
テスト例
import sys
import os
import time
import unittest
# utilsとpagesのフォルダーをインポートするためにPathを指定する
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from utils.driver_setup import DriverSetup
from pages.page_01_login import LoginPage
class LoginTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = DriverSetup().get_driver()
cls.login_page = LoginPage(cls.driver)
def test_google_login(self):
self.login_page.click_google_login()
time.sleep(1)
self.login_page.click_continue_ios_alert()
time.sleep(1)
self.login_page.click_existing_google_account()
time.sleep(3)
self.login_page.click_continue_login_button()
time.sleep(3)
if __name__ == '__main__':
unittest.main()
base.py
from selenium.webdriver.common.keys import Keys
class BasePage:
def __init__(self, driver):
self.driver = driver
# UI要素を見つける
def find_element(self, locator_type, locator):
return self.driver.find_element(locator_type, locator)
# UI要素をクリックする
def click(self, locator_type, locator):
self.find_element(locator_type, locator).click()
# 文字をタイプして内容を決定する
def enter_text(self, locator_type, locator, text):
self.find_element(locator_type, locator).send_keys(text)
# and click return
self.find_element(locator_type, locator).send_keys(Keys.RETURN)
utils
driver_setup.py
from appium import webdriver
from appium.options.ios import XCUITestOptions
class DriverSetup:
def __init__(self):
""" Set up desired capabilities for iOS Appium driver """
options = XCUITestOptions()
options.platform_name = 'iOS'
options.platform_version = '18.2'
options.device_name = 'iPhone 16 Pro'
options.app = 'path/to/your.app'
options.automation_name = 'XCUITest'
self.driver = webdriver.Remote('http://localhost:4723', options=options)
def get_driver(self):
return self.driver
config.py
# set as a config file
GOOGLE_ACCOUNT_NAME = "Your Name youraddress@gmail.com"
test_runner.py
import unittest
if __name__ == "__main__":
test_loader = unittest.TestLoader()
test_suite = test_loader.discover('tests')
test_runner = unittest.TextTestRunner()
test_runner.run(test_suite)
4. テストの実行
terminal内でcd コマンドでテストファイルの階層に移動したあと、テストを実行します
testsフォルダーにあるテストを全て実行する場合
python3 test_runner.py
一つのtestファイルのみ実行する場合
python3 tests/test_01_login.py