1. ホーム
  2. セレン

モバイルアプリの自動化 Appiumチュートリアル

2022-02-24 01:51:05
<パス

Appiumの原理とインストール

Appiumは、モバイルアプリ(携帯電話アプリ)の自動化ツールです。

モバイルアプリの自動化ってなんだろう?

  • 繰り返しの作業を自動化する
  • 例えば、WeChatのカスタマーサービスボット
  • クローラー
  • オートメーションテスト

自動化ソリューション「Appium」の特長。

  • オープンソースで無料
  • マルチプラットフォーム対応
  • 複数種類の自動化をサポート
  • 複数のプログラミング言語をサポート

自動化原理

Appiumの自動化の模式図を見てみましょう。


この写真に見覚えはありませんか?

はい、Seleniumの回路図によく似ていますね。なぜなら、Appiumの自動化アーキテクチャはSeleniumをベースにしているからです。

この図を見てください。この図には3つの主要な部分、すなわち自動化アプリケーション、Appium Server、およびモバイルデバイスが含まれています。

  • 自動化プロセス

    自動化プログラムは、特定の電話自動化機能を実装するために当社が開発したものです。

    また、特定のコマンドを発行して電話を制御するには、クライアント・ライブラリを使用する必要があります。

    また、Appium組織ではSeleniumと同様に、java、python、js、rubyなど複数のプログラミング言語用のクライアントライブラリを提供しており、異なるプログラミング言語の開発者でも容易に利用することが可能です。

    クライアントライブラリをインストールし、電話機に自動化コマンドを発行するために呼び出す必要があります。

  • Appiumサーバー

    Appium Serverは、Appiumの組織が開発したプログラムで、電話の自動化環境を管理し、自動化プログラムからの制御コマンドを電話に、電話からの応答メッセージを自動化プログラムに転送します。

  • モバイル機器

    携帯電話、タブレット、スマートウォッチなど、アップルやアンドロイドのモバイルデバイスのことです。

    可視化と説明のしやすさのために、略して「携帯電話」と呼ぶことにします。

    もちろん、携帯電話には、自動化・制御したいモバイルアプリのアプリも入っています。

    なぜモバイル機器は自動化コマンドを受信して処理できるのですか?

    Appium Serverが携帯電話に自動化エージェントをインストールし、自動化コマンドを待ち、実行するからです。

    例えば、ユーザーがインターフェイスのボタンをクリックすることをシミュレーションする場合、Appiumの自動化システムの流れは次のようになります。

  • オートメーションはクライアントライブラリの適切な関数を呼び出し、要素をクリックするコマンドを(HTTPメッセージにカプセル化されて)Appium Serverに送信します。

  • Appium Serverは、このコマンドを電話のオートメーションエージェントに転送します。

  • 電話の自動化エージェントはコマンドを受信し、電話のプラットフォーム上の自動化ライブラリを呼び出し、クリックを実行し、Appium Serverに成功したクリックを返します。

  • Appium Serverはオートメーションアプリケーションに転送する

  • 自動化プログラムは、この操作が成功したことを知ると、後で自動化プロセスを続行する

自動化エージェントが制御する場所では、自動化を実装するためにどのようなライブラリが使用されるのですか?

Appleの携帯電話でテストしている場合、AppleのXCUITestフレームワークを使用しています(IOSバージョン9.3以降)。

Android端末をテストする場合は、Android用のUIAutomatorフレームワークを使用します(Android 4.2以降)。

これらの自動化フレームワークは、モバイルデバイス上で動作するライブラリを提供し、プログラムがこれらのライブラリを呼び出すことで、人間のようにデバイスやアプリの操作(タップ、スワイプ、各種キーストローク・メッセージのシミュレーションなど)を自動化することが可能です。

自動化環境構築

このチュートリアルでは、Androidアプリの自動化に焦点を当てます。

環境構築にはかなりのソフトをダウンロード、インストールする必要があり、その多くは海外のサイトからダウンロードすることになります。

便宜上、ブログ主がこれらのソフトの最新インストーラーを以下のcsdnリソースに置いていますので、ご自身でダウンロードしてください。

リンク https://download.csdn.net/download/m0_50944918/14827713

クライアントプログラミングライブラリのインストール

回路図から、自動化アプリケーションは Appium Server と通信するためにクライアントライブラリを呼び出す必要があることがわかります。

今回はPython言語の開発を紹介するので、もちろんpipでインストールし、以下のようにします。

pip install appium-python-client


pycharmのユーザーは、設定からインストールできます。

Appiumサーバーのインストール

Appium Serverはnodejsで動作し、jsで開発されています。

Appiumの組織では、nodejsの実行環境、Appium Server、いくつかのツールをパッケージ化したAppium Desktopという実行ファイルを作成していますので、これをダウンロードしてインストールするだけで、簡単に利用することができます。

上記のリンクからダウンロードし、インストールすることができます。 Appium-windows-1.15.1.exe

公式ダウンロードアドレスはこちら

JDKのインストール

このチュートリアルでは、Androidアプリの自動化に焦点を当てますが、そのためにはAndroid SDKをインストールする必要があり(詳細は後述)、Android SDKはJDK環境を必要とします。

上記のリンクからダウンロードし、インストールすることができます。 jdk-8u211-windows-x64.exe

太字のスタイル
インストールしたら、環境変数も追加します。 JAVA_HOME を指定し、その値をjdkのインストールディレクトリとして指定します。

JAVA_HOME d:\tools\java\jdk1.8.0_211


Android SDKのインストール

Androidアプリの自動化には、Android SDKに加え、Appium Serverが必要です。

なぜなら、その中の次のようなツールの一部を使用するからです。 携帯電話のセットアップ、ファイル転送、アプリのインストール、携帯電話のインターフェイスの表示などのコマンドを実行するため。

androidsdk.zip をクリックし、解凍してください。

解凍後、環境変数を追加するように設定する必要があります。 ANDROID_HOME のように、sdkパッケージを解凍したディレクトリを値に設定します。 d:\tools ◇androidsdk

また、環境変数PATHにadbがあるディレクトリを含めるように設定することをお勧めします*。 d:\tools Indroidsdk ﹑platform-tools*

注意:それは 追加 このディレクトリを環境変数PATHに追加すると !!! 代わり映えしない!!! そうしないと、システムコマンドが見つからないので、初心者は、ビデオに従ってください。

携帯電話との接続

上記のソフトウェア環境が整ったところで、モバイルアプリを自動化するためには

アプリを起動しているパソコンで、Android端末をUSBケーブルで接続します

電話設定 -> 電話について を開き、バージョンメニューをクリックし続ける(7回以上)

上部メニューを終了し、開発者モードで、USBデバッグを有効にする

電話がUSBケーブルに接続されている場合、次のプロンプトと同様の電話インターフェースがポップアップ表示されます。


USBデバッグを許可する」を選択します。

注意事項

電話システムによっては、追加オプションの設定が必要な場合があります。

例えば、一部の機種では、USB経由でアプリをインストールできるようにするために開発者向けオプションをオンにする必要があるなどです。

要するに、USB開発デバッグをできるだけ簡単に携帯電話を制御できるようにすることです。

接続したら、コマンドラインウィンドウを開き、以下を実行します。 adb devices -l コマンドで、コンピュータに接続されているAndroidデバイスを一覧表示します。

以下のような出力になったら。

List of devices attached
4d0035dc767a50bb device product:t03gxx model:GT_N7100 device:t03g


接続された機器をコンピューターで確認でき、オートメーションプログラムを実行できることを示す。

事例紹介

csdnアプリを起動し、検索をクリックします。

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/1/18 19:11
# @Author : huni
# @File : APP.py
# @Software: PyCharm
from appium import webdriver
from appium.webdriver.extensions.android.nativekey import AndroidKey
from time import sleep

desired_caps = {
  'platformName': 'Android', # The phone under test is Android
  'platformVersion': '10', # Android version of the phone
  'deviceName': 'xxx', # the device name, you can fill in any Android phone
  'appPackage': 'net.csdn.csdnplus', # the name of the launch APP Package
  'appActivity': '.activity.SplashActivity', # the name of the startup Activity
  'unicodeKeyboard': True, # Use own input method, fill in True when inputting Chinese
  'resetKeyboard': True, # Restore the original input method after executing the program
  'noReset': True, # Don't reset the app
  'newCommandTimeout': 6000,
  'automationName' : 'UiAutomator2'
  # 'app': r'd:\apk\bili.apk',
}

# Connect to Appium Server and initialize the automation environment
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
sleep(4)
driver.find_element_by_class_name('android.widget.TextView').click()
sleep(5)
driver.quit()





コードを実行する前に Appium Desktop

アプリケーションパッケージとアクティビティの検索

apkがない。
すでにスマホにアプリがインストールされている場合は、直接スマホでアプリを開き、操作したいインターフェイスに移動することができます

次に実行します。

adb shell dumpsys activity recents | find "intent={"


は以下のように、直近の数件のアクティビティメッセージを表示します。

intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=tv.danmaku.bili/.ui.splash. SplashActivity}
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000300 cmp=com.huawei.android.launcher/.unihome. UniHomeLauncher}
intent={flg=0x10804000 cmp=com.android.systemui/.recents.RecentsActivity bnds=[48,1378][10322746]}
intent={flg=0x10000000 cmp=com.tencent.mm/.ui.LauncherUI}


apkで。
すでにapkを入手している場合は、コマンドラインウィンドウで実行する

d:\tools\androidsdk\build-tools\29.0.3\aapt.exe dump badging d:\tools\apk\bili.apk | find "package: name="


出力メッセージには、アプリのパッケージ名

package: name='tv.danmaku.bili' versionCode='5531000' versionName='5.53.1' platformBuildVersionName='5.53.1' compileSdkVersion='28' compileSdkVersionCodename='9'


コマンドラインウインドウで実行する

d:\tools\androidsdk\build-tools\29.0.3\aapt.exe dump badging d:\tools\apk\bili.apk | find "launchable-activity"


出力メッセージには、アプリの起動可能なActivity

launchable-activity: name='tv.danmaku.bili.ui.splash.SplashActivity' label='' icon=''


位置決め要素

コードのルール

サンプルコードから、Selenium Web Automationと同様に、インターフェイスの要素を操作するには、まず要素を配置(選択)する必要があることがわかると思います。

AppiumはSeleniumをベースにしているので、要素の位置決めの基本的なルールはSeleniumのコードと同じです。

find_element_by_XXX メソッドは、条件に一致する最初の要素を返し、見つからない場合は例外を投げます。

find_elements_by_XXX メソッドは、条件に一致するすべての要素のリストを返しますが、空リストではありません。

WebDriverオブジェクトからこのようなメソッドを呼び出すと、インターフェース全体を見ることができます。

このようなメソッドをWebElementオブジェクトで呼び出すと、そのノードの子オブジェクトを調べます。

インターフェース要素ビューアツール

Selenium Web Automation を行うときに要素を見つけるために、ブラウザの開発者ツールバーを使って要素のプロパティを表示し、それらのプロパティ(属性と位置)に基づいて、要素の位置を特定します。

Appium モバイルアプリを自動化するためには、インターフェース要素の特性を見るために同じツールが必要です。

一般的な閲覧ツールは:Android Sdk パッケージ uiautomateviewer Appium Desktop Appiumインスペクター

uiautomateviewer

Androidでアプリのインターフェイス要素を表示するために最もよく使われるツールは、Android SDKのuiautomateviewerで、SDKディレクトリのtoolsbinディレクトリに配置されています。

Seleniumと同様に、選択された要素の位置を特定したいのですが、これも以下のような要素の特徴に基づいています。

  • 要素の属性
  • 要素の相対位置(親要素、兄弟要素などとの相対的な位置関係)。

Appiumインスペクター

Appium Desktop Appiumインスペクター 要素も見ることができます。

その利点の1つは、選択式が要素の位置を特定することを直接確認できることです。

動画内の解説をご参照ください。

要素の配置方法

IDに基づく

Selenium Web Automationのチュートリアルでは、IDに基づいて位置決めされた要素を選択できるのであれば、そうするのがベストだと述べました。IDは一般的にユニークなので、IDに基づいて選択すると効率的だからです。

Androidアプリを自動化する場合、IDを基準に探す場合も同じようにできます。

しかし、このIDというのは、Androidアプリの要素のresource-id属性である

次のコードを使用します。

driver.find_element_by_id('expand_search')


CLASS NAMEによる。

Androidのインターフェース要素のclass属性は、実はWebのタグネームと同じように、要素のタイプに基づいているので、通常は一意ではありません。

通常、1つの要素を選択するのではなく、複数の要素を選択するために、class属性に基づいて要素を選択します。

もちろん、探しているタイプのインターフェイス要素が現在のインターフェイスにしかないことが確実な場合は、クラスに基づいて一意に選択することができます。

次のコードを使用します。

driver.find_elements_by_class_name('android.widget.TextView')


ACCESSIBILITY IDに基づく

要素のcontent-desc属性は、その要素が何を行うかを記述するために使用されます。

問い合わせるインターフェース要素にcontent-desc属性があれば、それを使って選択要素の場所を特定することができます。

次のコードを使用します。

driver.find_element_by_accessibility_id('find_person')


Xpath

AppiumはXpathによる要素選択もサポートしています。

しかし、その信頼性と性能はSelenium Web Automationほどではありません。なぜなら、Web AutomationのXpathのサポートはブラウザで実装され、AppiumのXpathのサポートはAppium Serverで実装されるからです。

やはり、ブラウザの製品はAppiumよりずっと成熟していますね。

もちろん、Xpathは標準的な構文なので、ここでの式の構文ルールは、以前習ったSeleniumのXpathの構文と同じで、次のようなものです。

driver.find_element_by_xpath('//ele1/ele2[@attr="value"]')


注意事項

selenium automation では、xpath 式の各ノード名が html のタグ名となります。

しかし、appiumでは、xpath式の各ノード名は、要素のclass属性の値です。

例:すべてのテキストノードを選択するには、次のコードを使用します。

driver.find_element_by_xpath('//android.widget.TextView')


Android UIAutomator

id、classname、accessibilityid、xpathをもとに要素を選択するメソッドは、実は一番下にあるAndroid uiautomatorフレームワークのAPI機能を利用して実装されています。

参考 Google Android 公式ドキュメントに記載されています。 https://developer.android.google.cn/training/testing/ui-automator

つまり、アプリケーションからのこれらの位置情報リクエストは、Appiumサーバーによってモバイルオートメーションエージェントに転送され、uiautomator内部の対応する位置情報関数の呼び出しに変換されます。

実際、私たちの自動化プログラムは、最も直接的な自動化制御のために、UI Automator API の java コードを呼び出すように、電話の自動化エージェントに直接指示することができます。

要素の位置決めは、主に以下のようなUiSelectorクラス内のメソッドで実現されます。

code = 'new UiSelector().text("hot").className("android.widget.TextView")'
ele = driver.find_element_by_android_uiautomator(code)
ele.click()


要素の位置を特定するのは、text属性とclassName属性です。

UiSelectorには、前のものが解決しない問題を解決する要素選択メソッドがあります。

例えば

  • テキストメソッド

    テキスト属性に基づいて要素を見つけることができます

  • テキストコンテナズ

    テキストがどのような文字列を含むかに基づいて

  • textStartsWith

    テキストがどのような文字列で始まるかに基づいて

  • textmartchメソッド

    以下のように、正規表現を使っていくつかの要素を選択することができます。

    code = 'new UiSelector().textMatches("^My. *")'
    
    
    

UiSelectorのインスタンスとインデックスは、どちらも0から数えて要素の位置を特定するために使うことができます。

  • instance は、マッチの結果に含まれるすべての要素のうち、最初の要素です。

  • indexは親要素のノード数で、xpathの*[n]に似ています。

UiSelectorのchildSelectorは、例えば以下のように子孫の要素を選択することができます。

code = 'new UiSelector().resourceId("tv.danmaku.bili:id/recycler_view").childSelector(new UiSelector().className(" android.widget.TextView"))'

ele = driver.find_element_by_android_uiautomator(code)


注意: childSelector の後の引用符は、子 uiSelector の式全体を囲む必要があります。