スポンサーリンク
目次
概要
以前にiPhoneアプリをAppiumで動かしてみましたが、今回はAndroidアプリのLINEを動かしてみました。
ラズパイ+Appium+PythonでiPhone自動テストを実行する方法
環境
(1) 制御対象:SH-M19, Androidバージョン13
(2) 制御元のマシン
・MacBook Pro M1 OSバージョン12.6
・Appium v2.0.0-beta.71
・Android Studio Flamingo | 2022.2.1 Patch 2
前準備
Appiumの公式ドキュメントをいきなり読み解くのが厳しかったので、以下の書籍を参考にPythonでAppiumを使うための基本を学習しました。
手順
Appiumの公式ドキュメント https://appium.io/docs/en/2.0/quickstart/ に沿ってセットアップします。
1. nodeインストール
Appiumを実行するためにnodeが必要となるため、まずはnodeを https://nodejs.org/ja/download からインストールします。
2. Appiumインストール
バージョン1.xと2.xがありますが、今回はベータ版の2.xをインストールします。
npm i -g appium@next
appium設定診断用ツールappium-doctorもインストールします。
npm install @appium/doctor -g
3. Android Studioインストール
Android Studioを公式サイト https://developer.android.com/studio からインストールします。
トップ画面のMore Actionsというメニューから「SDK Manager」を開きます。
SDK Toolsメニューで「Android SDK Platform-Tools」にチェックを入れてインストールしておきます。
4. Javaのインストール
OpenJDKを公式サイト https://openjdk.org/ からインストールします。
5. 環境変数を設定します。
インストールしたバージョン等により変わりますが、筆者の環境では以下のように設定しました。
$ nano ~/.bash_profile
export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"
export CPPFLAGS="-I/opt/homebrew/opt/openjdk@17/include"
export JAVA_HOME="/opt/homebrew/Cellar/openjdk@17/17.0.7/libexec/openjdk.jdk/Contents/Home"
export PATH=$JAVA_HOME/bin:$PATH
export ANDROID_HOME="/Users/mac/Library/Android/sdk"
export PATH=$PATH:$ANDROID_HOME/build-tools:$ANDROID_HOME/platform-tools
6. ドライバ追加
appium実行時に指定するドライバにはいくつか種類(espresso, xcuidriver等)がありますが、appium公式のドライバであるuiautomator2をインストールしました。
appium driver install uiautomator2
7. appium-doctor実行
WARNが複数出ていますがエラーは無かったので、このまま進めるものとします。
$ appium-doctor
WARN AppiumDoctor [Deprecated] Please use appium-doctor installed with "npm install @appium/doctor --location=global"
info AppiumDoctor Appium Doctor v.1.16.2
info AppiumDoctor ### Diagnostic for necessary dependencies starting ###
info AppiumDoctor ✔ The Node.js binary was found at: /Users/mac/.nvm/versions/node/v18.13.0/bin/node
info AppiumDoctor ✔ Node version is 18.13.0
info AppiumDoctor ✔ Xcode is installed at: /Applications/Xcode.app/Contents/Developer
info AppiumDoctor ✔ Xcode Command Line Tools are installed in: /Applications/Xcode.app/Contents/Developer
info AppiumDoctor ✔ DevToolsSecurity is enabled.
info AppiumDoctor ✔ The Authorization DB is set up properly.
info AppiumDoctor ✔ Carthage was found at: /opt/homebrew/bin/carthage. Installed version is: 0.38.0
info AppiumDoctor ✔ HOME is set to: /Users/mac
info AppiumDoctor ✔ ANDROID_HOME is set to: /Users/mac/Library/Android/sdk
info AppiumDoctor ✔ JAVA_HOME is set to: /opt/homebrew/Cellar/openjdk@17/17.0.7/libexec/openjdk.jdk/Contents/Home
info AppiumDoctor Checking adb, android, emulator, apkanalyzer
info AppiumDoctor 'adb' is in /Users/mac/Library/Android/sdk/platform-tools/adb
info AppiumDoctor 'emulator' is in /Users/mac/Library/Android/sdk/emulator/emulator
WARN AppiumDoctor ✖ android, apkanalyzer could NOT be found in /Users/mac/Library/Android/sdk!
info AppiumDoctor ✔ 'bin' subfolder exists under '/opt/homebrew/Cellar/openjdk@17/17.0.7/libexec/openjdk.jdk/Contents/Home'
info AppiumDoctor ### Diagnostic for necessary dependencies completed, one fix needed. ###
info AppiumDoctor
info AppiumDoctor ### Diagnostic for optional dependencies starting ###
WARN AppiumDoctor ✖ opencv4nodejs cannot be found.
info AppiumDoctor ✔ ffmpeg is installed at: /opt/homebrew/bin/ffmpeg. ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers
WARN AppiumDoctor ✖ mjpeg-consumer cannot be found.
WARN AppiumDoctor ✖ set-simulator-location is not installed
WARN AppiumDoctor ✖ idb and idb_companion are not installed
WARN AppiumDoctor ✖ applesimutils cannot be found
info AppiumDoctor ✔ ios-deploy is installed at: /opt/homebrew/bin/ios-deploy. Installed version is: 1.11.4
WARN AppiumDoctor ✖ bundletool.jar cannot be found
WARN AppiumDoctor ✖ gst-launch-1.0 and/or gst-inspect-1.0 cannot be found
info AppiumDoctor ### Diagnostic for optional dependencies completed, 7 fixes possible. ###
info AppiumDoctor
info AppiumDoctor ### Manual Fixes Needed ###
info AppiumDoctor The configuration cannot be automatically fixed, please do the following first:
WARN AppiumDoctor ➜ Manually install android, apkanalyzer and add it to PATH. https://developer.android.com/studio#cmdline-tools and https://developer.android.com/studio/intro/update#sdk-manager may help to setup.
info AppiumDoctor
info AppiumDoctor ### Optional Manual Fixes ###
info AppiumDoctor The configuration can install optionally. Please do the following manually:
WARN AppiumDoctor ➜ Why opencv4nodejs is needed and how to install it: http://appium.io/docs/en/writing-running-appium/image-comparison/
WARN AppiumDoctor ➜ mjpeg-consumer module is required to use MJPEG-over-HTTP features. Please install it with 'npm i -g mjpeg-consumer'.
WARN AppiumDoctor ➜ set-simulator-location is needed to set location for Simulator. Please read https://github.com/lyft/set-simulator-location to install it
WARN AppiumDoctor ➜ Why idb is needed and how to install it: https://github.com/appium/appium-idb
WARN AppiumDoctor ➜ Why applesimutils is needed and how to install it: http://appium.io/docs/en/drivers/ios-xcuitest/
WARN AppiumDoctor ➜ bundletool.jar is used to handle Android App Bundle. Please read http://appium.io/docs/en/writing-running-appium/android/android-appbundle/ to install it
WARN AppiumDoctor ➜ gst-launch-1.0 and gst-inspect-1.0 are used to stream the screen of the device under test. Please read https://appium.io/docs/en/writing-running-appium/android/android-screen-streaming/ to install them and for more details
info AppiumDoctor
info AppiumDoctor ###
info AppiumDoctor
info AppiumDoctor Bye! Run appium-doctor again when all manual fixes have been applied!
info AppiumDoctor
8. LINEのappPackageとappActivityを確認
appiumから操作するAndroidデバイスを指定するためには「appPackage」と「appActivity」という情報が必要です。
調べてみると、以下コマンドで現在開いているアプリのappPackageとappActivityを確認できるようであったんので、LINEアプリを開いた状態でコマンドを実行した。
$ adb shell dumpsys window | grep 'mCurrentFocus'
mCurrentFocus=Window{9322240 u0 jp.naver.line.android/jp.naver.line.android.activity.main.MainActivity}
appiumから制御できるか確認するためのコマンドが以下のようなので試してみたが、Exceptionが発生してしまいました。
$ adb shell am start -W -n jp.naver.line.android/jp.naver.line.android.activity.main.MainActivity -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000
Stopping: jp.naver.line.android
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jp.naver.line.android/.activity.main.MainActivity }
Exception occurred while executing 'start':
java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jp.naver.line.android/.activity.main.MainActivity } from null (pid=26059, uid=2000) not exported from uid 10430
at com.android.server.wm.ActivityTaskSupervisor.checkStartAnyActivityPermission(ActivityTaskSupervisor.java:1145)
at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1045)
at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:729)
at com.android.server.wm.ActivityTaskManagerService.startActivityAndWait(ActivityTaskManagerService.java:1559)
at com.android.server.am.ActivityManagerService.startActivityAndWait(ActivityManagerService.java:3255)
at com.android.server.am.ActivityManagerShellCommand.runStartActivity(ActivityManagerShellCommand.java:602)
at com.android.server.am.ActivityManagerShellCommand.onCommand(ActivityManagerShellCommand.java:208)
at com.android.modules.utils.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:97)
at android.os.ShellCommand.exec(ShellCommand.java:38)
at com.android.server.am.ActivityManagerService.onShellCommand(ActivityManagerService.java:9374)
at android.os.Binder.shellCommand(Binder.java:1049)
at android.os.Binder.onTransact(Binder.java:877)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:4763)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2721)
at android.os.Binder.execTransactInternal(Binder.java:1285)
at android.os.Binder.execTransact(Binder.java:1244)
https://testerhome.com/topics/15973 によると、「必要なのは、メインインターフェイス上の現在のアクティビティではなく、開始されたアクティビティです」ということで、ログを観測してみるとLINEアプリ起動時に
cmp=jp.naver.line.android/.activity.SplashActivity
というアクティビティが起動していました。
$ adb logcat ActivityManager
(省略)
06-10 14:47:17.359 1730 2409 W InputReader: Received unexpected event (0x35, 0x67) for slot 0 with tracking id 52584
06-10 14:47:17.359 1730 2409 W InputReader: Received unexpected event (0x36, 0x3ab) for slot 0 with tracking id 52584
06-10 14:47:17.430 1730 5165 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jp.naver.line.android/.activity.SplashActivity bnds=[23,788][230,1131]} from uid 10211
06-10 14:47:17.470 18105 18118 D MainProcessObserver: pid:5959 uid:10430 foregroundActivities:true
06-10 14:47:17.470 1730 19735 W ActivityTaskManager: MANAGE_ACTIVITY_STACKS is deprecated, please use alternative permission: MANAGE_ACTIVITY_TASKS
06-10 14:47:17.487 18105 18118 D onForegroundChanged: topActivity:ComponentInfo{jp.naver.line.android/jp.naver.line.android.activity.main.MainActivity}, taskId:16606, windowingMode:1
06-10 14:47:17.487 18105 18118 D onForegroundChanged: packageName:jp.naver.line.android
06-10 14:47:17.511 1730 3036 D ConnectivityService: requestNetwork for uid/pid:10430/5959 activeRequest: null callbackRequest: 47376 [NetworkRequest [ REQUEST id=47377, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10430 RequestorUid: 10430 RequestorPkg: jp.naver.line.android UnderlyingNetworks: Null] ]] callback flags: 0 order: 2147483647
06-10 14:47:17.517 17983 20829 V EventRepository: onChangeForeground(jp.naver.line.android, 16606)
再度、appiumからの制御確認コマンドを叩いてみると、今度は処理が成功してAndroid端末上でもLINEが起動することを確認できました。
$ adb shell am start -W -n jp.naver.line.android/.activity.SplashActivity -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000
Stopping: jp.naver.line.android
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jp.naver.line.android/.activity.SplashActivity }
Status: ok
LaunchState: COLD
Activity: jp.naver.line.android/.activity.main.MainActivity
TotalTime: 1377
WaitTime: 1389
Complete
9. Pythonサンプルコード
LINEをホーム画面から起動し、公式アカウント画面に遷移するサンプルを動作させました。
import pytest
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
class Test:
@pytest.fixture(autouse=True)
def setup(self):
desired_caps = {
"platformName": "Android",
"appium:platformVersion": "13",
"appium:automationName": "UiAutomator2",
"appium:deviceName": "SH-M19",
"appPackage": "jp.naver.line.android",
"appActivity": ".activity.SplashActivity",
"appium:noReset": True,
"appium:fullReset": False,
}
self.driver = webdriver.Remote('http://localhost:4723', desired_caps)
yield
self.driver.quit()
def test_sample(self):
self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="ホームタブ 選択中").click()
self.driver.find_element(by=AppiumBy.XPATH, value="//android.widget.RelativeLayout[@content-desc=\"公式アカウント\"]/android.widget.ImageView").click()
10.参考図書
日本語では、Appium+Pythonを解説する書籍を見つけられなかったので、英語ですが以下のKindle本を参考にしました。