Appiumを使ったモバイルアプリのUIテスト自動化
Appiumを使ったモバイルアプリのUIテスト自動化
エンジニアの藤原です。
今回はAppiumを使ったモバイルアプリの自動テストについて 書いていきたいと思います。
Appiumとは
Webアプリケーションのテスト自動化フレームワークの1つにSeleniumがあります。
AppiumはSeleniumベースのモバイルアプリテスト自動化フレームワークです。
今回は、Monacaのアプリに対してこのAppiumを用いてUIの自動テストを書いてみたいと思います。
まずは結果から
長い説明に入る前に結果からお見せします。
このようにアプリが自動的に起動してUIの操作が行われます。
用意するもの
アプリ
テスト対象のアプリには先日リリースされたバーコードスキャナープラグインのサンプルアプリを使用します。
こちらのプロジェクトをMonacaにインポートしてデバッグビルドし、出力結果のapkファイルをダウンロードしておきます。
テスト端末
今回はandroidのみを対象とします。
Android Studioをインストールし、エミュレータを1つ起動できる状態にしておきます。
デバイス名(AVD Name)を後ほど使用します。
Appium
Appiumはサーバー+クライアントの構成になっています。
Appiumで検索すると、Appium Desktop, Appium Studioなど色々なものが引っかかります。
どれを入れたらいいかわからなくなりますが、今回は公式のGUI版を選択します。
以前はAppium Desktop
と呼ばれていたアプリケーションが現在はAppium Server GUI
、Appium Inspector
の2つに分離されています。
Appium Server GUI(旧Appium Desktop)
Mac /Windowsの場合はこちらからアプリケーションを入手可能です。
インストール手順については公式のドキュメントを参照してください。
テストクライアント
Appiumに対応したテストフレームワークを利用できます。
今回はpythonのpytestを採用しました。
pytest+Appiumの実行に必要なコンポーネントについては公式のrequirements.txtを参考にしてください。
テスト作成の流れ
テストは以下の流れて作っていきます
- テストケース(テストシナリオ)の検討
- テストコードを書く
テストケース(テストシナリオ)の検討
テストのシナリオとしては以下の流れを自動的に実行することにします。
テストシナリオ
- アプリインストール → 起動 → スキャナ画面表示 → 画面上のメッセージ文字列検出
チェック項目
- 各操作がエラーなく実行できること
- 数秒経過後にバーコード未検出のメッセージ"Not detected"が表示されること
本当はバーコードが正しくスキャンされたことをテストしたいところですが、カメラの撮影の自動化は困難なため、今回はスキャンされなかったケースをテスト対象とします。
なお、画面遷移が正しく行われていることを確認するために各画面でスクリーンショットを撮ります。
テストコードを書く
公式のサンプルコードを基にテストシナリオのコードを書いてみました。
サンプルアプリのtest
フォルダにテストファイルが格納されています。
test/util.py
初期設定
# Appiumサーバへの接続情報
APPIUM_SERVER = "http://127.0.0.1:4723/wd/hub"
# テストするアプリのapkファイルパス
ANDROID_APP_PATH = "./app-debug.apk"
# スクリーンショットの保存先
SCREENSHOTS_DIR = "screenshots"
# desired capabilities(common)
def get_desired_capabilities_base():
# (略)
# スクリーンショット有効
caps["appium:nativeWebScreenshot"] = True
# (略)
# desired capabilities for android
def get_desired_capabilities_android():
# (略)
# 以下の設定で、テスト毎にアプリを再インストール
caps["app"] = appPath
caps["allowTestPackages"] = True # True: package for simulator
caps["enforceAppInstall"] = True # re-install app before test
# (略)
test/test_android.py
テ スト初期化
- 端末の指定
作成しておいたエミュレータ名を設定
DEVICE_NAME = "Pixel_5_API_31"
- Appiumサーバとの接続
@pytest.fixture
def fixture_driver():
# setup(before test)
caps = util.get_desired_capabilities_android()
caps["appium:avd"] = DEVICE_NAME
# start appium session
return webdriver.Remote(util.APPIUM_SERVER, caps)
テストシナリオの実行
- スクリーンショットを撮る
# スクリーンショット1枚目 - アプリ起動直後
sleep(5)
fixture_driver.save_screenshot(settings['screenShotsBase'] + "_01.png")
- UIを操作して画面遷移
# "スキャン" をタップ
el1 = fixture_driver.find_element(by=AppiumBy.XPATH, value="//*[@resource-id='scan']")
el1.click()
# カメラの使用を許可
sleep(2)
fixture_driver.save_screenshot(settings['screenShotsBase'] + "_02.png")
# カメラの許可をタップ
el2 = fixture_driver.find_element(by=AppiumBy.ID, value=settings['cameraArrowButtonId'])
el2.click()
- 数秒経過後、"Not detected"のメッセージが表示されているかどうか確認
# check timeout prompt
el3 = fixture_driver.find_elements(by=AppiumBy.ID, value="com.example.helloworld:id/timeout_prompt")
# メッセージ文字列が一致すればテストSUCCESS
assert len(el3) > 0 and el3[0].text == "Not detected"
# quit
fixture_driver.quit()
テスト実行
手順
Appium Server GUIを起動し、テストコードに記載した通りの設定に合わせて"Start Server"を実行します。
APPIUM_SERVER = "http://127.0.0.1:4723/wd/hub"
ターミナルからpytestを実行すると自動テストが開始されます。
cd test
pytest test_android.py
結果
実行すると前述の動画の通り、自動的に操作が行われます。
全てのテストケース(今回は1つだけ)がpass
していれば成功となります。
この通り画面遷移する度にスクリーンショットも撮れています。
このようにして自動的にエミュレータ上でアプリの操作が行われること、期待したテスト結果が得られることが確認できました。
補足
この記事では結果を見て頂くことに焦点を置きましたので、途中の苦労した点などには触れていません。
実際に動作させる上でハマりそうな点を簡単にまとめておきます。
操作対象の要素の取得
el1 = fixture_driver.find_element(by=AppiumBy.XPATH, value="//*[@resource-id='scan']")
この行のような操作対象の要素をいかに取り出せるかがテストコードを書く上での一番のポイントになるかもしれません。
こちらについては説明が長くなるので、需要があればまた改めて解説したいと思います。
- Appium Inspector などを用いて要素を調べる
- アプリの開発の時点でユニークなIDを割り当てるなどしておくことで、要素の特定がし易くなる
UI自動テストでできること・できないこと
- できること・向いてること
- 繰り返し同じ操作を行う
- 複数の端末で実行する
- 異なるOSやさまざまなバージョンのテストを行う
- 実機でも実行できる
- WebView、ネイティブUIどちらでも操作できる
- できないこと・向いてないこと
- 画面に表示されていない情報の取得。WebAPIの実行結果など
- 動作に実時間+αの時間がかかる
- シビアなタイミングが要求される操作の実行は厳しい
まとめ
このようにMonacaアプリのテストを自動化してみました。
Monacaチームでは今後増えていくテンプレートやプラグインのテスト手法として自動テストを検証しており、その一部を今回の記事で紹介させて頂きました。
また新たな発見などあればブログで紹介させて頂きます。