ネイティブアプリ向けのUIテスト環境であるappiumをiOS環境へ導入しようしたところ、iOS向け環境構築のまとまったドキュメントがなかったため、ここにまとめます。
前提
前提として、iOSのサンプルアプリ程度を作成できる程度の知識・スキルを読者に要求します。ご容赦ください。
appiumとは
appiumは、WebDriverを使用してAndroidまたはiOSでネイティブアプリケーション、モバイルWebアプリケーション、およびハイブリッドアプリケーションをテストするためのオープンソース自動化ツールです。
仕組みについては、Appiumの仕組みと使い方やAppium 2.0 ではじめるモバイルアプリテストをご参考ください。
実行環境
- macOS 12.0.1
- XCode 13.3.1
環境構築手順
macOSやXcodeといったiOSアプリ開発に必須の環境構築については、ここでは省略します。
1. サンプルアプリの準備
次にXCodeでiOSのサンプルアプリを準備します。
アプリ名はご自身で適当につけて構いません。
ただし、テストコードを作成する際にBundle Identifier
が必要となるため、ここでメモします。
UIはStoryBoardを選択します。
プロジェクトを作成したら、以下のコードをViewController.swift
にコピー&ペーストします。
import UIKit
class ViewController: UIViewController {
private let textFieldSize = CGSize(width: 200, height: 100)
private let textField: UITextField = {
let field = UITextField()
field.borderStyle = .bezel
// appiumのクライアントがUIを識別するために
// Accessibility Identifierを設定します
field.accessibilityIdentifier = "textField"
return field
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.addSubview(self.textField)
}
override func viewWillLayoutSubviews() {
let x = self.view.frame.midX - self.textFieldSize.width/2
let y = self.view.frame.midY - self.textFieldSize.height/2
self.textField.frame = CGRect(origin: CGPoint(x: x, y: y), size: self.textFieldSize)
}
}
ビルドします。
ビルドのターゲットは、筆者は15.4
、iPhone 11
を選択しました。
ビルドし、アプリを立ち上げると以下の画面になります。
2. nodeのインストール
nodeがインストールされていない場合は、brewでnodeをインストールします
brew install node
3. appium(サーバサイド)のセットアップ
appiumのサーバ実行環境にはCLI版とGUI版が存在します。CLIの操作に慣れていない方はGUI版をおすすめします。GUI版はここから、もしくはbrewでインストールできます。
ここでは、CLI版のインストールについて記述します。
appiumの公式ドキュメントにしたがって、appiumをインストールします。
npm install -g appium
次にappiumの依存関係を検証するappium-doctorをインストールします
npm install -g appium-doctor
appium-doctorを実行し、環境を検証します。
appium-doctor --ios
依存関係が解消できていない場合は、appium-doctorの出力に従って、必要なアプリケーションをインストールします。
筆者の環境では、carthageというライブラリ管理ソフトウェアが足りないとのことなので、brewでcarthageをインストールしました
brew install carthage
4. appium(クライアント側)の準備
appiumのサーバは、WebDriverの標準プロトコルに対応しているため、javaやruby、javascript、pythonといったさまざまな言語に対応しています。
ここでは、python3のクライアントについて説明します。
まず、適当なディレクトリとmain.py
作成します
mkdir appium-client
cd appium-client
touch main.py
次に、pip3でappiumのpython3クライアントをインストールします
pip3 install Appium-Python-Client
5. テストの作成
クライアントをインストールしたら、具体的なテストの作成に移ります。
テストの完成形は次のようになります。
次のコードをmain.py
にコピー&ペーストします。
ペーストしたら、bundleIdをStep1で作成したプロジェクトのbundler
import os
import sys
import unittest
import socket
from time import sleep
from appium import webdriver
class AppiumTest(unittest.TestCase):
def setUp(self):
options = {
'logLevel': 'info',
'platformName': 'iOS',
'deviceName': 'iPhone 11',
'platformVersion': '15.4',
'automationName': 'XCUITest',
'bundleId': 'own.SampleApp', # ここを編集
}
protocol = 'http'
host = socket.gethostname()
ipaddress = socket.gethostbyname(host)
port = '8100'
path = '/wd/hub'
self.driver = webdriver.Remote(f'{protocol}://{ipaddress}:{port}{path}', options)
def tearDown(self):
self.driver.quit()
def test_textfield(self):
element = self.driver.find_element_by_accessibility_id("textField")
# 値を取得
value = element.get_attribute('value')
self.assertEqual(value, None)
# テキストを入力
word = "Hello, World!"
element.send_keys(word)
# 値を取得
value = element.get_attribute('value')
self.assertEqual(value, word)
if __name__ == '__main__':
# テストを実行
suite = unittest.TestLoader().loadTestsFromTestCase(AppiumTest)
unittest.TextTestRunner(verbosity=2).run(suite)
6. テストの実行
テストが作成できたので、テストを実行します。
テストを実行するためにまず、iOS Simulatorを立ち上げます。
open -a Simulator.app
次にappiumのサーバを立ち上げます。
ローカルIPアドレスを取得するために、python3をコマンドライン実行しています。
appium --address `python3 -c "import socket; print(socket.gethostbyname(socket.gethostname()))"` --port 8100
共に立ち上がったら、最後にテストを実行します
python3 main.py
出力は次のようになるはずです。(Deprecatedはここでは無視しています)
test_textfield (__main__.AppiumTest) ... [Deprecated] Please use 'find_element' with 'AppiumBy.ACCESSIBILITY_ID' instead.
ok
----------------------------------------------------------------------
Ran 1 test in 4.234s
OK
以上です。