広告

Selenium と Appium で macOS, iOS, Android のブラウザを自動操作する件

実機を使って Selenium と Appium を試してみました。

やりたいことは下記の通りです。

  • Selenium を使用して macOS の Safari と Google Chrome を自動操作
  • Appium を使用して macOS から iOS (iPhone) の Safari や Android の Chrome を自動操作

環境

  • Mac (macOS 10.13.4 High Sierra)
  • iPhone 7 (iOS 11.3.1)
  • Nexus 6P (Android 8.1.0)

Homebrew と Python

パッケージ管理システムの Homebrew をインストールし、Python をインストールします。なお、macOS にはデフォルトで /usr/bin/python に Python 2 がインストールされています。

今回の事例では Python 3 のみを使用します。

Homebrew
https://brew.sh/

Python 3 をインストールします。/usr/local/bin/python3 にインストールされます。

brew install python
# Python 3.6.5

macOS デフォルトの Python 2 を使いたくない場合、brew で Python 2 をインストールできます。/usr/bin/python ではなく、/usr/local/bin/python が使われるようになります。

brew install python@2
# Python 2.7.10

ちなみに、Pyhton 3 と Python 2 の環境を綺麗に切り分けたい場合、virtualenv を使用するのが一般的のようです。

#pip3 install virtualenv
#virtualenv -p `which python3` --no-site-packages env
#source env/bin/activate

Selenium

まず、macOS の Safari と Google Chrome を自動操作するために Selenium をインストールします。

pip3 でインストールしようとしたところ、デフォルトでインストールされていました。つまり、brew で python 3 をインストールした時点で Selenium もインストールされていると。

pip3 install selenium
# Requirement already satisfied: selenium in /usr/local/lib/python3.6/site-packages (3.12.0)

Safari

Selenium で macOS の Safari を操作する場合、ドライバは必要ないようです。Safari の設定を行うのみです。

Safari のメニューから Preferences… を起動し、Advanced タブを選択します。”Show Develop menu in menu bar” にチェックを入れます。次に Safari の Develop メニューから “Allow Remote Automation” にチェックを入れます。

簡単な動作確認用スクリプトを作成してみます。Safari を自動起動し、Google のサイトを開き、3秒後に Safari を自動終了させるだけです。

# coding:utf-8
  
from selenium import webdriver
from time import sleep

driver = webdriver.Safari()
driver.get("https://www.google.co.jp")
sleep(3)
driver.close()

実行して期待通りの挙動をすることを確認します。

python3 test.py

Google Chrome

Selenium で macOS の Google Chrome を操作する場合、chromedriver をインストールしておく必要があるようです。

brew install chromedriver
Error: No available formula with the name "chromedriver" 
It was migrated from homebrew/core to caskroom/cask.
You can access it again by running:
  brew tap caskroom/cask
And then you can install it by running:
  brew cask install chromedriver

何も考えずにインストールしようとするとエラーになるため、Homebrew-Cask からインストールします。

brew tap caskroom/cask
brew cask install chromedriver

簡単な動作確認用スクリプトを作成してみます。Google Chrome を自動起動し、Google のサイトを開き、3秒後に Google Chrome を自動終了させるだけです。

# coding:utf-8
  
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get("https://www.google.co.jp")
sleep(3)
driver.close()

実行して期待通りの挙動をすることを確認します。

python3 test.py

Appium

Appium
http://appium.io/

iOS の Safari, Android の Chrome を自動操作するために、macOS に Appnium をインストールします。まず、brew に node をインストールした後に npm で appium をインストールします。

brew install node
npm install -g appium
npm install wd

iOS

Appium で iOS デバイス実機を操作する場合、https://appium.io/docs/en/drivers/ios-xcuitest-real-devices/ に一通り書かれています。

iOS デバイスの実機を自動操作したい場合、まず、Apple Developer Program に参加しておく必要があります。現時点では年間 11,800 yen です。

Apple Developer Program
https://developer.apple.com/programs/jp/

その後、macOS に Xcode をインストールし、iOS デバイスを開発用デバイスとして登録しておきます。今回は iOS デバイスとして iPhone を使用します。Xcode のバージョンは 9.3.1 です。

Xcode でプロジェクトを作成します。iOS の Single View App とし、Product Name を適当に設定し、Team を設定します。

Xcode のプロジェクトの Targets の Signing で、Team を設定します。Provisioning Profile が “Xcode Managed Profile” に設定され、Signing Certificates が “iPhone Developer: Name (XXXXX)” に設定されることを確認します。

macOS に iPhone を USB 接続します。Xcode の Window メニューの Devices and Simulators をクリックすると、接続されている iPhone の Identifier を確認できます。

この Single View App を iPhone 実機で実行できることを確認します。

実行できることが確認できれば、Xcode を終了させます。

Apple Developer Program の Account https://developer.apple.com/account/ にアクセスし、ログインします。Membership で、Team ID を確認します。

iPhone の設定 – Safari – 詳細で、Web インスペクタを有効にしておきます。

macOS に戻り、必要なパッケージをインストールしていきます。

brew install carthage
brew install libimobiledevice
brew install ios-deploy
brew install ios-webkit-debug-proxy

npm install appium-ios-driver
npm install -g ios-deploy

まず、ターミナルで ios_webkit_debug_proxy を実行します。

ios_webkit_debug_proxy -c <iPhone の Identifier>:27753 -d

iPhone の画面に、「このコンピュータを信頼するか」とか「パスコードを入力しろ」とか表示されます。

ios_webkit_debug_proxy の実行後、下記のようなエラーとなる場合、

Listing devices on :9221
Could not connect to lockdownd. Exiting.: Permission denied
Unable to attach xxxxx inspector

/var/db/lockdown のパーミッションを変更します。

chmod +x /var/db/lockdown

ios_webkit_debug_proxy の実行後、下記のようなエラーとなる場合、

Listing devices on :9221
Could not connect to lockdownd. Exiting.: Operation now in progress
Unable to attach xxxxx inspector 

最新の libimobiledevice をインストールしてみます。

brew unlink libimobiledevice
brew install autoconf
brew install automake
brew install libtool
brew install pkg-config
brew install --HEAD libimobiledevice

次に Appium をオプション付きで実行します。例えば下記の通り。

appium --default-capabilities '{"browserName":"Safari", "deviceName":"iPhone", "udid":"iPhone の Identifier", "xcodeOrgId":"Apple Developer Program の Team ID", "xcodeSigningId":"iPhone Developer"}'

正常に起動すると、TCP:4723 で待ちます。

[Appium] Welcome to Appium v1.8.0
[Appium] Non-default server args:
[Appium]   defaultCapabilities: {
[Appium]     browserName: Safari
[Appium]     deviceName: iPhone
[Appium]     udid: xxx
[Appium]     xcodeOrgId: xxx
[Appium]     xcodeSigningId: iPhone Developer
[Appium]   }
[Appium] Default capabilities, which will be added to each request unless overridden by desired capabilities:
[Appium]   browserName: Safari
[Appium]   deviceName: iPhone
[Appium]   udid: xxx
[Appium]   xcodeOrgId: xxx
[Appium]   xcodeSigningId: iPhone Developer
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

簡単な動作確認用スクリプトを作成してみます。Safari を自動起動し、Google のサイトを開き、3秒後に Safari を自動終了させるだけです。

# coding:utf-8
  
from selenium import webdriver
from time import sleep

capabilities = {'platformVersion':'11.3', 'deviceName':'iPhone', 'platformName':'iOS', 'browserName':'Safari'}

driver = webdriver.Remote('http://localhost:4723/wd/hub', capabilities)
driver.get('https://www.google.co.jp')
sleep(3)
driver.close()

実行して期待通りの挙動をすることを確認します。macOS でスクリプトを実行すると、iPhone の Safari が起動するはずです。

python3 test.py

下記のようなエラーとなる場合、

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not determine Xcode version: Could not get Xcode version. /Library/Developer/Info.plist does not exist on disk.

下記のコマンドを実行し、Appium を再起動し、再度スクリプトを実行してみます。

sudo xcode-select --switch /Applications/Xcode.app

下記のようなエラーとなる場合、署名に失敗している可能性があるので、xcodeOrgId (Team ID) や xcodeSigningId (固定値 “iPhone Developer”) が正常に設定されているか、スペルミスが無いか等を確認してみます。

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Unable to launch WebDriverAgent because of xcodebuild failure: "xcodebuild failed with code 65". Make sure you follow the tutorial at https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md. Try to remove the WebDriverAgentRunner application from the device if it is installed and reboot the device.

署名に失敗すると、WebDriverAgentRunner-Runner.app が生成されず、自動操作に失敗します。

[Xcode] 2018-05-12 15:10:08.597 xcodebuild[22158:343521] Error Domain=NSCocoaErrorDomain Code=260 "The file “WebDriverAgentRunner-Runner.app” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/hirooka/Library/Developer/Xcode/DerivedData/WebDriverAgent-brdadhpuduowllgivnnvuygpwhzy/Build/Products/Debug-iphoneos/WebDriverAgentRunner-Runner.app, NSUnderlyingError=0x7fc272c364f0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
[Xcode] 
[Xcode] 2018-05-12 15:10:08.597 xcodebuild[22158:343521] Error Domain=IDETestOperationsObserverErrorDomain Code=6 "Early unexpected exit, operation never finished bootstrapping - no restart will be attempted" UserInfo={NSLocalizedDescription=Early unexpected exit, operation never finished bootstrapping - no restart will be attempted, NSUnderlyingError=0x7fc2728b9690 {Error Domain=NSCocoaErrorDomain Code=260 "The file “WebDriverAgentRunner-Runner.app” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/hirooka/Library/Developer/Xcode/DerivedData/WebDriverAgent-brdadhpuduowllgivnnvuygpwhzy/Build/Products/Debug-iphoneos/WebDriverAgentRunner-Runner.app, NSUnderlyingError=0x7fc272c364f0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}}}
[Xcode] 
[Xcode] 
[Xcode] Testing failed:
[Xcode] 	No signing certificate "iOS Development" found:  No "iOS Development" signing certificate matching team ID "48496HAS6F" with a private key was found.
[Xcode] 
[Xcode] 	Early unexpected exit, operation never finished bootstrapping - no restart will be attempted
[Xcode] ** TEST EXECUTE FAILED **
[Xcode] 
[Xcode] 
[XCUITest] xcodebuild exited with code '65' and signal 'null'
[debug] [BaseDriver] Event 'wdaStartFailed' logged at 1526105408617 (15:10:08 GMT+0900 (JST))
[debug] [XCUITest] Unable to launch WebDriverAgent because of xcodebuild failure: "xcodebuild failed with code 65". Make sure you follow the tutorial at https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md. Try to remove the WebDriverAgentRunner application from the device if it is installed and reboot the device.
[debug] [XCUITest] Quitting and uninstalling WebDriverAgent, then retrying

Android

macOS に Android Studio, あるいは Android command line tools をインストールし、adb コマンドへのパスを通しておきます。

https://developer.android.com/studio/

例えば下記の通り。

export PATH=$PATH:/Users/hirooka/Library/Android/sdk/platform-tools

Android の設定 – システム – 端末情報のビルド番号を連打タップして開発者向けオプションを有効にします。Android の設定 – システム – 開発者向けオプションで、USB デバッグを有効にします。

Android デバイスを macOS に USB 接続します。adb コマンドで Android デバイスが認識されていることを確認します。

adb devices

List of devices attached
* daemon not running; starting now at tcp:5037
* daemon started successfully
xxxxxxxxxxxxxxxx	device

adb サーバーを起動します。

adb start-server

ChromeDriver のパスをオプションに付けて appium を起動します。

appium --chromedriver-executable /usr/local/bin/chromedriver

Appium は、TCP:4723 を使用するようです。

[Appium] Welcome to Appium v1.8.0
[Appium] Non-default server args:
[Appium]   chromedriverExecutable: /usr/local/bin/chromedriver
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

簡単な動作確認用スクリプトを作成してみます。Chrome を自動起動し、Google のサイトを開き、3秒後に Chrome を自動終了させるだけです。

# coding:utf-8
  
from selenium import webdriver
from time import sleep

capabilities = {'platformVersion':'8.1', 'deviceName':'Android', 'platformName':'Android', 'browserName':'Chrome'}

driver = webdriver.Remote('http://localhost:4723/wd/hub', capabilities)
driver.get('https://www.google.co.jp')
sleep(3)
driver.close()

実行して期待通りの挙動をすることを確認します。macOS でスクリプトを実行すると、Android の Chrome が起動するはずです。

python3 test.py

なお、Android のネイティブアプリはスコープ外として、Android でウェブアプリだけを自動操作するなら Appium は必要なく、ChromeDriver のみでいけます。

ChromeDriver – WebDriver for Chrome
http://chromedriver.chromium.org/getting-started/getting-started—android

とはいえ、Appium を使うと capabilities を切り換えるだけで iOS でも Android でもスクリプトを共通化できるため、クロスデバイスでテストするのに便利です。

広告

Appium

Posted by admin