Automate E2E Testing on Cloud (Appium & Azure Pipelines)

この記事は、[ソフトウェアテスト Advent Calendar 2022](https://qiita.com/advent-calendar/2022/softwaretesting)の11日目の記事となります。
前日10日の記事は、@cvusk さんの「[ソフトウェアテストの実行を効率化するPredictive Test Selectionの衝撃](https://qiita.com/cvusk/items/358e7964927af4128d32)」でした。

https://qiita.com/advent-calendar/2022/softwaretesting

https://qiita.com/cvusk/items/358e7964927af4128d32

## 概要

スマホアプリを[Azure Piplines](https://azure.microsoft.com/ja-jp/services/devops/pipelines/)でCI対応した後にビルドしたアプリが問題なく起動して動作するか簡単なE2Eテストを[Appium](https://appium.io/)を用いて実行する環境を作ってみました。

今回は、iOSアプリを対応したものでAndroidアプリ~~やUnity~~のビルド後のアプリビルドの対応については後日やってみようかと。

※Unityなど3Dエンジンをもとに描画した画面ではAppiumはサポートされておらず、スクリーンショット撮影するとブラックスクリーンの画像が生成され、OpenCVの画像認識によるボタンクリック操作を実行しても反応しませんでした。

### 注意

本記事では、Azure PipelinesでのCI/CDやAppiumのE2Eテストツール関連について初心者向けへの解説は特にしません。

初めて知る方などは、過去に以下の記事にそれらの解説をまとめており、入門・初心者的な他の記事を参考に一度触ってから参考にされてください。

https://qiita.com/gremito/items/265d15d6fcf53db3db2d

https://qiita.com/gremito/items/08d44b5e18afe05910a5

https://qiita.com/gremito/items/81d595e8282a91bbfd8d

https://qiita.com/gremito/items/41cf9a0c8d27eccdf165

### その他の知見

かれこれ2~3年前から触ってまして、過去の知見は以下になります。

https://qiita.com/gremito/items/793e74df2083546af4c1

https://qiita.com/gremito/items/b87bf035870b7a34d07b

https://qiita.com/gremito/items/b989476e4e023ded538c

## 仕組み

AppiumをAzure Pipelinesに組み込んだCI/CDについて、以下のワークフローで実装しました。
（※Azure Pipelinesからフローが流れているのは、CI開始の意味でもちろん全てAzure Pipelines環境内で起きている。）

まず、正常に`.app`および`.ipa`のアプリビルドされた後にAppiumを実行します。
AppiumによるE2Eテストが問題なければ、[AppCenter](https://appcenter.ms/)にアプリデプロイするシンプルなフローとなります。

<img width="600px" alt="スクリーンショット 2022-06-03 12.20.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/da96454f-ef6a-d35f-894a-47c3f56939cb.png">


### AppCenterTest

今回は、Azure Pipelinesに強引にAppium環境をインスコしたやり方となり、App CenterでAppiumテストできる設定があるようです。

https://docs.microsoft.com/ja-jp/azure/devops/pipelines/ecosystems/android?view=azure-devops#test

https://docs.microsoft.com/ja-jp/azure/devops/pipelines/ecosystems/xcode?view=azure-devops#testing-on-azure-hosted-devices

https://docs.microsoft.com/ja-jp/azure/devops/pipelines/tasks/test/app-center-test?view=azure-devops

https://docs.microsoft.com/ja-jp/appcenter/test-cloud/vsts-plugin

https://docs.microsoft.com/ja-jp/appcenter/test-cloud/frameworks/appium/

## 今回使用するアプリのサンプルについて

今回使用したサンプルは、Xcodeのデフォルトで用意されているプロジェクト`Page Based Application`を活用しました。
このサンプルは、左右のスワイプで次と前の画面に遷移できる作りで、画面上に表示されている文字の確認やボタンクリック以外のテスト操作も必要なケースを想定したいと思い使いました。

<img width="600px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/771a6d3a-671a-a5d3-43be-b4c878ceb8be.png">

<img width="300px" alt="スクリーンショット 2022-06-03 13.50.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/9ca8ef95-cc55-8ac3-ae27-5718b6518c3f.png">


## Azure Pipelines に Appium 環境を構築する

きっかけは、

https://ki4070ma.com/20210309_appium-azure/ 

の記事を見つけてやってみたものの、ここで解説されている`.yml`だけではエラーになりました。

### `azure-pipelines.yml`

上記の記事をもとに最新に対応してエラーなく、AppiumをAzure Pipelinesに組み込むだけの設定内容を以下のGistにまとめています。

https://gist.github.com/gremito/f710f8975b43bf9a64737164ea993205


## iOSシミュレータ

もともと`.ipa`ビルド向けに対応していたため、`.app`ビルド(iOSシミュレーター)向けについてやったことがなく、こちらも調査して試してみました。
諸々ググったところ、関連する記事が少なかったりそれぞれ設定ばバラバラで苦戦しました。

今回は、以下の内容で`.app`ビルドをやっています。
また、手元でXcode上でビルドするときとxcodebuildコマンドとで`.app`がビルドされるパスが異なるので、初回は手動で`.app`ファイルを探して扱いやすい場所にコピーしておくと管理しやすいと思い以下のようにしました。

```yml
- task: Xcode@5
  inputs:
    actions: 'clean build'
    sdk: 'iphonesimulator'
    configuration: 'Release'
    xcWorkspacePath: './*.xcodeproj'
    scheme: '$(XCODE_PROJECT_NAME)'
    xcodeVersion: 'default'
    destinationPlatformOption: 'iOS'
    destinationTypeOption: 'simulators'
    destinationSimulators: 'iPhone 13'

- script: |
    echo "# ls -lt /Users/runner/Library/Developer/Xcode"
    ls -lt /Users/runner/Library/Developer/Xcode/DerivedData/$(XCODE_PROJECT_NAME)-*/Build/Products/Release-iphonesimulator

    echo "# mkdir $(agent.buildDirectory)/output/iphoneos/Release-iphonesimulator"
    mkdir -p $(agent.buildDirectory)/output/iphoneos/Release-iphonesimulator

    echo "# cp -r ~/build/Release-iphonesimulator/$(XCODE_PROJECT_NAME).app"
    cp -r /Users/runner/Library/Developer/Xcode/DerivedData/$(XCODE_PROJECT_NAME)-*/Build/Products/Release-iphonesimulator/$(XCODE_PROJECT_NAME).app $(agent.buildDirectory)/output/iphoneos/Release-iphonesimulator/
  displayName: "Check Path & Cp App"
```

https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/xcode?view=azure-devops#yaml-snippet


## Pytest
Pythonは、インスコできてもpytestは入っていないのでこれも手動でインスコしてから`pytest`を実行、テストコードの中で状況を把握するためにテスト中のスクリーンショットを撮っているので、その画像データを`PublishBuildArtifacts`するパスにコピーしています。

```yml
- script: |
    echo "# pip3 install pytest"
    pip3 install pytest
    
    echo "# python3 -m pytest ./test/AppiumTest.py"
    python3 -m pytest ./test/AppiumTest.py

    echo "# cp screenshot image agent.buildDirectory/output"
    cp ./test/screenshot_*.png $(agent.buildDirectory)/output
  displayName: Install pytest & Pytest appium.
```

### E2E Test Code

サンプルで作った`AppiumTest.py`の中身について、以下のGistにまとめています。

https://gist.github.com/gremito/509064955bf88caa5780cf614a1d5273


Appium Desktopは、クリック以外のスクロール/スワイプや長押しの操作が用意されていないようなので、下記リンク先のAPIリファレンスや各リポジトリを参考に各自でテストコードを調整する必要があります。


https://appium.io/docs/en/about-appium/api/

https://github.com/appium/python-client#quick-migration-guide-from-v1-to-v2


### 処理時間

上記のサンプルだけでも以下の結果で51分半ほどかかっているため、ガッツリ開発しているアプリのXcodeビルドが長かったり、FlutterやUnityなどのマルチプラットフォームビルドができる開発ツールだともっと時間がかかることが想像できます。


<img width="650px" alt="スクリーンショット 2022-06-04 17.48.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/5a467082-0bc8-ccc1-ea7c-fa800a8de6c9.png">


## まとめ

実際に正常に終わって`PublishBuildArtifacts`した成果物が以下の内容です。
これで、Azure PipelinesでAppiumが実行できる環境ができ、アプリデプロイ前にビルドしたアプリが正常に起動して最低限動作するか簡単に確認するE2Eテストをクラウド上で完結させることができました。

<img width="350px" alt="スクリーンショット 2022-06-04 17.47.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4d7b0536-c388-a1b3-a01c-fc4edf9ba4ec.png">
<br>
<img width="250px" alt="screenshot_20220623154623.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/8a8862c3-7c9b-793d-7dba-fe2876506a7b.png">
<img width="250px" alt="screenshot_20220623154625.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/1d6946fa-69f0-136b-dd5e-3603df02d272.png">
<img width="250px" alt="screenshot_20220623154626.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/0240ef00-e777-2d35-f0f4-e0d0cd6ba981.png">

### 課題

E2Eテスト環境ができてこれで終わりではなく、次のような課題についてさらに対策が必要となります。

- バージョンやテストなど諸々のメンテナンス
- E2Eテスト結果の可視化
- CI/CDにかかる時間の最適化
- 属人化対策