エンジニアの藤原です。
今回はAppiumを使ったモバイルアプリの自動テストについて書いていきたいと思います。
Webアプリケーションのテスト自動化フレームワークの1つにSeleniumがあります。
AppiumはSeleniumベースのモバイルアプリテスト自動化フレームワークです。
今回は、Monacaのアプリに対してこのAppiumを用いてUIの自動テストを書いてみたいと思います。
長い説明に入る前に結果からお見せします。
このようにアプリが自動的に起動してUIの操作が行われます。
テスト対象のアプリには先日リリースされたバーコードスキャナープラグインのサンプルアプリを使用します。
こちらのプロジェクトをMonacaにインポートしてデバッグビルドし、出力結果のapkファイルをダウンロードしておきます。
今回はandroidのみを対象とします。
Android Studioをインストールし、エミュレータを1つ起動できる状態にしておきます。
デバイス名(AVD Name)を後ほど使用します。
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を参考にしてください。
テストは以下の流れて作っていきます
テストのシナリオとしては以下の流れを自動的に実行することにします。
本当はバーコードが正しくスキャンされたことをテストしたいところですが、カメラの撮影の自動化は困難なため、今回はスキャンされなかったケースをテスト対象とします。
なお、画面遷移が正しく行われていることを確認するために各画面でスクリーンショットを撮ります。
公式のサンプルコードを基にテストシナリオのコードを書いてみました。
サンプルアプリのtest
フォルダにテストファイルが格納されています。
# 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
# (略)
DEVICE_NAME = "Pixel_5_API_31"
@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")
# "スキャン" をタップ
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()
# 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']")
この行のような操作対象の要素をいかに取り出せるかがテストコードを書く上での一番のポイントになるかもしれません。
こちらについては説明が長くなるので、需要があればまた改めて解説したいと思います。
このようにMonacaアプリのテストを自動化してみました。
Monacaチームでは今後増えていくテンプレートやプラグインのテスト手法として自動テストを検証しており、その一部を今回の記事で紹介させて頂きました。
また新たな発見などあればブログで紹介させて頂きます。