search
LoginSignup
1
Help us understand the problem. What are the problem?

posted at

updated at

appiumのiOS用テスト環境を構築する

ネイティブアプリ向けの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.4iPhone 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

以上です。

参考文献

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?