GitHub ActionsでAppiumの画像セレクタを使う
こんにちは、自動化エンジニアの森川です。
今日はAppiumの画像セレクタ機能を用いたE2EテストをGitHub Actions上で動かしてみたいと思います。
きっかけ
Appiumの画像解析機能は、画像による要素指定や画像マッチングができるのでユースケースによっては非常に有用だと思います。ただしAppium本体とは別にopencv4nodejsが必要なのでセットアップにひと手間がかかります。ただでさえセットアップに手間のかかるAppium環境に、もうひと手間かかるのは正直つらいです。
また、筆者はWindowsユーザーなのでiOSの検証環境が常に手元にありません。普段はクラウドテストサービスで済ませていますが、opencv4nodejsはクラウド側の環境に準備されていなかったり、対応が限定的だったりします※1。そこでGitHub ActionsのHosted-Runnerを使ってクラウド上で実現できないかと思い立ちました。
コードはこちらに公開しています。
tmshft/appium-image-detection-example
尚、本記事ではAppiumやGitHub Actionsの基本的なところは触れません。
※1 BrowserStackではリアルデバイスのみ対応しているようです。SauceLabsは2018年からリクエストされたままです。
Requesting support for OpenCV - Sauce Labs Customer Idea Portal
トライアル環境
・Java:AdoptOpenJdk11
・Gradle:6.8.3
・Appium Java Client:7.4.1
・Appium: 1.18.3
・opencv4nodejs: 3.4.6
・macOS:10.15(latest)
・XCode:12.0.1
・iOS:14.0(Simulator)
参考リンク
・Image Comparison - Appium
・Finding Image Elements - Appium
Hosted Runner
MacOS10.15Hosted-runnerを使います。今回は利用制限の無いPublicリポジトリで挑戦しています。理由はビルドに時間がかかり、Privateリポジトリだと利用制限にすぐ達してしまうからです。特に時間を要するのはopencv4nodejsの導入で1stepに15分以上かかるなんていうのもザラです。このあたりはEnterpriseプランであればビルド資産をCacheする方がよさそうです。
テストケース
検証アプリは弊社のテストツール検証用アプリを使いました。
イメージで要素を選択してクリック、テンプレート・マッチングで結果確認するというシンプルなテストです。
Appium設定
DesiredCapabilities readCapabilities() {
DesiredCapabilities capabilities = new DesiredCapabilities();
//...(中略)
capabilities.setCapability("settings[getMatchedImageResult]", true);
capabilities.setCapability("settings[imageMatchThreshold]", 0.8);
return capabilities;}
・getMatchedImageResult:イメージセレクタの結果画像データ維持
・imageMatchThreshold:比較時のしきい値設定
テストコード
@Test
void imageSelectorTest() throws IOException, InterruptedException {
// イメージセレクタ
WebElement loginElm = driver.findElementByImage(getReferenceImageB64("racine_sut_login.png"));
// visualization
String imageResult = loginElm.getAttribute("visual");
// Allureにアタッチ(サービス関数経由)
addAttachment(Base64.getDecoder().decode(imageResult), "image-selector");
loginElm.click();
Thread.sleep(10000);
// テンプレート・マッチング
OccurrenceMatchingResult result = templateMatch("original_template.png");
// Allureにアタッチ(サービス関数経由)
addAttachment(Base64.getDecoder().decode(result.getVisualization()), "template-matched-result");
assertNotNull(result.getRect());
}
イメージセレクタは、AppiumDriverのfindElementByImage APIにイメージのデータをbase64形式で渡すだけです。
テンプレート・マッチングはfindImageOccurrence APIを用います。こちらは2つのイメージファイルとオプションを渡しています。
// サービス関数
private OccurrenceMatchingResult templateMatch(String template) throws IOException {
return driver
.findImageOccurrence(
driver.getScreenshotAs(OutputType.FILE),
new File(resourceDir + template),
new OccurrenceMatchingOptions()
.withThreshold(0.6)
.withEnabledVisualization());
}
ワークフロー
PRされたらワークフローが走ってテストを実行して結果をPRにコメントするという流れです。
name: Appium iOS gui test example
on:
pull_request:
branches:
- "*"
jobs:
build:
name: Native App Test
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
name: checkout
- name: checkout app as git submodule
run: |
echo "${{ secrets.codecommit_key }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
export GIT_SSH_COMMAND="ssh -v -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -l ${{ secrets.codecommit_id }}"
git submodule add --force ${{ secrets.codecommit_sut_repo }} ./sut_app
git submodule update -i --remote
- name: specify valid Xcode Version
run: sudo xcode-select -s /Applications/Xcode_12.0.1.app
- name: set up node.js
uses: actions/setup-node@v1
with:
node-version: '10.16.3'
- name: set up opencv4nodejs
run: |
brew install cmake
npm install -g opencv4nodejs
- name: set up Appium
run: |
npm install -g appium@1.18.3
appium --log-timestamp --log-no-colors > appium.log &
- name: execute test
run: |
chmod +x ./gradlew
./gradlew clean test allureReport
- name: deploy to pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: build/reports/allure-report
publish_branch: test-report
if: always()
- name: comment to pr
uses: actions/github-script@0.3.0
if: github.event_name == 'pull_request'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
github.issues.createComment({ issue_number, owner, repo, body: 'ci-test report<br/><a href="[repository url]">see report</a>' });
CIパイプライン全般に言えるのですが、デバッグができないのでステップごとに慎重に書いていくしかないです。ときにはls,pwdコマンドを使ってヨチヨチと確認をして問題解決していきます。
※ SSHでデバッグできるコマンドがあると社内指摘をいただきました。今回は試していません、次回に是非!
各ステップはコメントのとおりなので、ポイントだけ抜粋します。
- name: checkout app as git submodule
検証用アプリをGitのSubModuleとして某所からチェックアウトしています。アカウント情報はあらかじめGitHubのSecretsに設定しておきます。
- name: set up opencv4nodejs
opencv4nodejsのインストール
- name: execute test
テスト実行とあわせてレポートの出力のGradleタスクallureReportを実行します。
deploy to pages ~ comment to pr
結果レポートをGitHub Pagesにパブリッシングして、PRスレッドにコメント投稿しています。
いずれもGitHubマーケットプレースでよさそうだったActions(Module的なもの)を使わせてもらいました。
※ GitHub Marketplaceにはセキュア上よろしくないActionsも公開されているそうなのでご利用には十分ご注意ください。
実行結果
実行結果を見てみましょう。
現物はこちらです。
https://tmshft.github.io/appium-image-detection-example/
結果レポートは美しさで定評のAllure Reportを使っています。ActionsのArtifactにアップロードするだけでもよいのですが、ZIPファイルをダウンロードして閲覧する手間がとっても面倒なので、GitHub Pagesで1クリックで見られるようにしています。
イメージセレクタ
要素検索に使用したイメージファイル
一致結果
イメージセレクタとして認識された要素が赤線で囲まれているのがわかります。イメージセレクタのマッチ画像取得はたった1行書くだけです。
// Visualization
String imageResult = loginElm.getAttribute("visual");
// Allureレポートにアタッチ(サービス関数経由)
addAttachment(Base64.getDecoder().decode(imageResult), "image-selector");
ただし上述のとおりCapabilitiesでgetMatchedImageResultをtrueにしておく必要があります。
テンプレートマッチ
テンプレート・イメージファイル
ログイン後の画面に表示される「テスト項目」のイメージが含まれているかどうかを検証しています。
赤線で囲まれていますね。(サンプルアプリの地色も弊社のイメージカラー「赤」なので恐ろしくわかりにくいですね!)
マッチ結果はgetVisualizationで取得します。
こちらも事前にOccurrenceMatchingOptions.withEnabledVisualizationしておきます。
まとめ
Appiumとopencv4nodejsの面倒なセットアップからテストとレポーティングまでを、実にわずかなコードで書けることがわかりました。物理端末のセットアップとくらべると作業時間の差は歴然だと思います。ただクラウド+リモートなので、トラブルシューティングが難しいという弱点はあります。
そして本トライアルはあくまでサンプルです。実際の運用では様々な要素が絡み合いますので、解決に追われることになります。
DPI値
デバイスによってDPI値が異なりますので比較イメージをリサイズしてやる必要があります。OSによって表示内容が変わる場合はそれぞれの要素画像を用意しないといけません。
要素が見つからない場合の対策
要素が見つからない場合の分岐処理や画像比較時のしきい値のチューニングが必要になるでしょう。
パフォーマンス
画像判定処理をしている分、当然パフォーマンスは下がります。もとより速いとは言えないAppiumなので、テスト実行の全体にかかる時間が膨らみすぎないように工夫が必要になるでしょう。
キャッシュ化
これはGitHub Actions側の問題ですね。アプリケーションを毎回クリーンインストールしていると時間がかかりますのでキャッシュで高速化するべきですが、無限ではないので今度はキャッシュ管理という手間が発生します。
また今回のトライアルの状態ではレポートが実行毎に上書きされてしまいますので、履歴を残すようにするべきです。
このように、さっと思いつくだけでも様々な点について考慮する必要があります。
おまけ
最後に宣伝です。
弊社のGUI自動化ツールRacineではPC-Webブラウザでもイメージセレクタ機能をご利用いただけます。またGUI自動テストでのGitHub Actions導入実績やノウハウがございます。
SHIFTのGUIテストツールRacineとその開発プロセス
お客様のニーズにあわせて自動化アーキテクトが過去のナレッジを生かした柔軟な対応をすることで最適なE2E自動テストを提供いたします。
__________________________________
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/