Jenkins で Airetest を Device Farm でE2Eテスト実行するCIを作った

本記事は、[ソフトウェアテストの小ネタ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/software-testing-koneta) 20日目の記事です。

## 概要

[AWS Device Farm](https://aws.amazon.com/jp/device-farm/)で[Appium](https://appium.io/)をPytestでE2Eテストするにあたって基本的な情報をまとめています。

## 導入

まずは、一般的な使い方やハマりやすいポイントを解説します。

### Console

・プロジェクトを用意後に新しく実行を設定する際に新たにアプリファイルをアップロードかすでにアップロード済みのアプリを指定


<img width="650px" alt="スクリーンショット 2022-09-06 10.13.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/642b775d-82e8-cbba-6493-6e3359c045c9.png">

・テストの種類を指定するセレクトから `Appium Python` を選んで[公式にある通り作成](https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/test-types-appium.html)した `test_bundle.zip` をアップロードかすでにアップロード済みのZipファイルを指定

<img width="650px" alt="スクリーンショット 2022-09-06 10.14.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/8affd398-1545-a8d5-2bf9-33f36bd32ed2.png">

・TestSpecの設定は**Configure画面上で表示されているテキストを編集しても適応されない**ため`Edit`ボタンから`Edit your YAML`上で編集して`Save as New`ボタンで保存してから適応

<img width="650px" alt="スクリーンショット 2022-09-06 10.15.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/57477b4e-91ee-d0a5-8084-762f366fb07e.png"> <img width="650px" alt="スクリーンショット 2022-09-06 10.15.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/90f5c144-1352-0c7e-a6ff-cf1f8fc2a7a3.png">　<img width="650px" alt="スクリーンショット 2022-09-06 10.16.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/7327b7c1-78a0-53bf-1ee4-0ffbf6b9779a.png">

・テスト対象のデバイスの指定はデフォルトでも問題ないがOSのバージョンを別々に実行したいテストや特定のデバイスを限定して実行したいテストがある場合は前もって`device pool`を作成して実行する

<img width="650px" alt="スクリーンショット 2022-09-06 10.16.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/1b4d0348-cd9f-1a39-8c2e-5f6e3af398ca.png"> <img width="650px" alt="スクリーンショット 2022-09-06 18.59.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/06612c10-ebc4-e14f-c7f1-5c170d9e8a27.png">

・デフォルトのTestSpecに設定されている`$DEVICEFARM_LOG_DIR`にテストスクリプトで生成したログやスクショのファイルを保存しておくと実行履歴からテストのFilesタブにある`Customer Artifacts`のリンクからファイルをダウンロードすることができる

<img width="650px" alt="スクリーンショット 2022-09-06 19.17.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/c344fe9a-1a36-face-6f2b-5d453fb717c4.png">


### requirements.txt

公式で

> WorkSpace で次のコマンドを実行して、requirements.txt ファイルを生成します。
> 
> 　$ pip freeze > requirements.txt

と解説があるものの補足がないため初見ではわかりにくい。
すでにローカルでAppiumをPytestで実装済みであれば、このコマンドでインストール済みのpip群を出力できるもののDevice Farmがサポートする環境に適していないpipやバージョンが多く、例えば以下のようなエラーが発生する。

- ERROR: Could not find a version that satisfies the requirement numpy==1.22.3
- ERROR: Failed building wheel for PyNaCl
- CMake Error: CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.

そのため必要最低限のpip群だけ記述した`requirements.txt`を出力するため、PytyonのDockerコンテナのイメージを作って`Appium-Python-Client`をインストールした余計なものが入っていない環境下で`pip freeze > requirements.txt`を実行してDevice Farmにアップロードしたところ、Device Farm側で用意されるiOS向けの環境では問題なかったもののAndroid向けの環境では上記の`CMake Error`が起きて、このエラーの解消はどうしても対応できませんでした。

結論としては、`pip freeze > requirements.txt`はやらずにPytestのコード上でimportしているライブラリのみ指定すればよく、あとはよしなにDevice Farm側で必要なpip群を自動でインストールしてくれる仕組みになっている。
そのため、Appiumのみであれば

```:requirements.txt
Appium-Python-Client==2.6.0
pytest==7.1.2
```

を記載（バージョンはよしなに調整）した`requirements.txt`をアップロードすれば、問題なくPytestでAppiumのテストがiOS/Androidの両方で問題なく正常動作しました。

### `test_bundle.zip`の作り方

https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/test-types-appium.html#test-types-appium-create-a-zip

## 応用

ここからは、Device Farmを活用したトピックを解説します。

### Airtest

ネイティブアプリだけでなくUnityやCocos2dxなどの[3DCG API](https://docs.unity3d.com/ja/2022.2/Manual/GraphicsAPIs.html)を用いて作られたアプリにもE2Eテストができる[Airtest](https://github.com/AirtestProject/Airtest)をDevice FarmのAppiumサポートを通して実行することもできました。

#### Android

https://hackerslab.aktsk.jp/2022/07/15/154102

参考にした上記のアカツキさんの記事のまま対応してみたところ、TestSpecの`$adb_path=$(which adb)`で

```
[DeviceFarm] $adb_path=$(which adb)
/tmp/scratchKdJ6cj.scratch/shell-script-ZUpYYv/shell_script.sh: 125: /tmp/scratchKdJ6cj.scratch/shell-script-ZUpYYv/shell_script.sh: =/opt/dev/android-sdk-linux/platform-tools/adb: not found
```

とエラーになってしまったため、確実に取得できるよう以下のように調整することで回避できました。

```yml:testspec_for_android.yml
      - ls -l ./lib/python3.7/site-packages/airtest/core/android/static/
      - rm ./lib/python3.7/site-packages/airtest/core/android/static/adb/linux/adb
      - adb_path=`which adb`
      - echo $adb_path  # 確認できるよう念のため出力しておく
      - cp $adb_path ./lib/python3.7/site-packages/airtest/core/android/static/adb/linux/adb
      - sed -i -e s#^\$ADB#$adb_path.orig#g ./lib/python3.7/site-packages/airtest/core/android/static/adb/linux/adb
```

#### iOS

Airtestの公式には詳細がないため、iOSサポートの実装が似ているAltUnityTesterの公式ドキュメント

https://altom.com/altunity/docs/altunitytester/pages/tester-with-cloud.html#aws-device-farm

で解説されている内容がAirtestでもおそらく同様の問題で対応できない模様。

> We encountered some problems forwarding the port on iOS devices. This why we only talk about running tests on Android devices. We will update this page and the sample project once we have a solution for iOS.
> 
> [翻訳: DeepL]
> iOSデバイスでポートの転送に問題が発生しました。このため、Androidデバイスでのテスト実行についてのみ説明しています。iOS用のソリューションができ次第、このページとサンプルプロジェクトを更新します。

そのサンプルプロジェクト

https://gitlab.com/altom/altunity/examples

を確認するとローカルで実装する際に参考になるサンプルは豊富で

https://gitlab.com/altom/altunity/examples/alttrashcat-tests-python-aws/-/blob/master

のプロジェクトでDevice Farmのサンプルとしては不足していてこの内容では実装できなかった。

ただし

https://gitlab.com/altom/altunity/examples/ios-build-with-python-tests/-/blob/master/ios_tests.sh

などのサンプルでシェルスクリプトでの実行方法や

```bash
iproxy 13000 13000 $DEVICE_UDID &
```

で`iproxy`をデーモン起動できることなどが知れたので参考になる情報が多くありました。


### AWS CLI: `$ aws devicefarm`

https://qiita.com/VA_nakatsu/items/d74814cfcbd8975cbb11

こちらの記事で、device farmのコマンドについてわかりやすくまとめられていてとても参考になった。
~~`$ aws devicefarm get-run`でコンソール上から操作して実行したテストのリストを取得して実行時間をざっと算出したが、なぜか`An error occurred (ArgumentException) when calling the GetRun operation: Invalid arn ...`になってしまってできなかったため残念・・・~~


#### テストの実行

https://docs.aws.amazon.com/cli/latest/reference/devicefarm/schedule-run.html

`schedule-run`でテストを実行することができる。
すでにアップロードしているファイルを指定するケースの場合、以下のように各arnを取得してJsonを準備して`--cli-input-json`オプションにセットする。

```shell
# すでにアップロードしているアプリファイルのarnを取得する
% aws devicefarm list-uploads --arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) --region=us-west-2 --type=IOS_APP
{
    "uploads": [
        {
            "arn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(APP_UPLOAD_ID)",
            "name": "PageBasedSample.ipa",
            "created": "2022-10-04T17:23:33.510000+09:00",
            "type": "IOS_APP",
            "status": "SUCCEEDED",
            "url": "https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A$(ACCOUNT_ID)%3Aproject%3A$(PROJECT_ID)/uploads/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A$(ACCOUNT_ID)%3Aupload%3A$(PROJECT_ID)/$(APP_UPLOAD_ID)/PageBasedSample.ipa?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20221011T043929Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20221011%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=$(SIGNATURE_ID)",
            "metadata": "{\"activity_name\":\"\",\"minimum_arm\":6,\"error_type\":null,\"package_name\":\"net.gremito.app.ios.PageBasedSample\",\"sdk_version\":1210,\"files\":{},\"warning_type\":null,\"supported_os\":\"12.1\",\"executable\":\"PageBasedSample\",\"platform\":[\"iPhoneOS\"],\"form_factor\":[1,2]}",
            "contentType": "application/octet-stream",
            "category": "PRIVATE"
        }
    ]
}

# すでにアップロードしている`test_bundle.zip`のarnを取得する
% aws devicefarm list-uploads --arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) --region=us-west-2 --type=APPIUM_PYTHON_TEST_PACKAGE
{
    "uploads": [
        {
            "arn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(TEST_PACKAGE_UPLOAD_ID)",
            "name": "test_bundle.zip",
            "created": "2022-10-04T17:23:41.907000+09:00",
            "type": "APPIUM_PYTHON_TEST_PACKAGE",
            "status": "SUCCEEDED",
            "url": "https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A$(ACCOUNT_ID)%3Aproject%3A$(PROJECT_ID)/uploads/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A$(ACCOUNT_ID)%3Aupload%3A$(PROJECT_ID)/$(TEST_PACKAGE_UPLOAD_ID)/test_bundle.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20221011T043947Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20221011%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=$(SIGNATURE_ID)",
            "metadata": "{\"valid\":true}",
            "contentType": "application/octet-stream",
            "category": "PRIVATE"
        }
    ]
}

# すでにアップロードしているTestSpecのarnを取得する。
% aws devicefarm list-uploads --arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) --region=us-west-2 --type=APPIUM_PYTHON_TEST_SPEC  
{
    "uploads": [
        ...
        {
            "arn": "arn:aws:devicefarm:us-west-2::upload:$(TEST_SPEC_UPLOAD_ID)",
            "name": "TestSpec v7.0 for iOS Appium Python (sets Python version 3 as the default)",
            "created": "2021-10-26T00:37:02.386000+09:00",
            "type": "APPIUM_PYTHON_TEST_SPEC",
            "status": "SUCCEEDED",
            "url": "https://prod-us-west-2-uploads-testspec.s3-us-west-2.amazonaws.com/public-yaml-files/appium_119_python_3_ios.yml?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20221011T044001Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20221011%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=$(SIGNATURE_ID)",
            "category": "CURATED"
        },
        ...
    ]
}

# すでに作成しているDevice Poolのarnを取得する
% aws devicefarm list-device-pools --arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) --region=us-west-2
{
    "devicePools": [
        ...
        {
            "arn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):devicepool:$(PROJECT_ID)/$(DEVICEPOOL_ID)",
            "name": "iphones",
            "type": "PRIVATE",
            "rules": [
                {
                    "attribute": "ARN",
                    "operator": "IN",
                    "value": "[\"arn:aws:devicefarm:us-west-2::device:$(DEVICE_ID)\"]"
                }
            ]
        }
    ]
}

# `schedule-run`にセットするJsonを作成する
% cat <<EOF > ~/execTest.json
> {
    "projectArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID)",
    "appArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(APP_UPLOAD_ID)",
    "devicePoolArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):devicepool:$(PROJECT_ID)/$(DEVICE_POOL_ID)",
    "name": "202210111605",
    "test": {
        "type": "APPIUM_PYTHON",
        "testPackageArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(TEST_PACKAGE_UPLOAD_ID)",
        "testSpecArn": "arn:aws:devicefarm:us-west-2::upload:$(TEST_SPEC_UPLOAD_ID)"
    },
    "configuration": {
        "locale": "ja_JP"
    }
}
EOF

# テストを実行する
% aws devicefarm schedule-run --region=us-west-2 --cli-input-json file:///Users/gremito/execTest.json 
{
    "run": {
        "arn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):run:$(PROJECT_ID)/$(RUN_ID)",
        "name": "202210111605",
        "type": "APPIUM_PYTHON",
        "platform": "IOS_APP",
        "created": "2022-10-11T16:06:44.681000+09:00",
        "status": "SCHEDULING",
        "result": "PENDING",
        "started": "2022-10-11T16:06:44.681000+09:00",
        "counters": {
            "total": 0,
            "passed": 0,
            "failed": 0,
            "warned": 0,
            "errored": 0,
            "stopped": 0,
            "skipped": 0
        },
        "totalJobs": 1,
        "completedJobs": 0,
        "billingMethod": "METERED",
        "appUpload": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(APP_UPLOAD_ID)",
        "jobTimeoutMinutes": 150,
        "devicePoolArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):devicepool:$(PROJECT_ID)/$(DEVICEPOOL_ID)",
        "locale": "ja_JP",
        "radios": {
            "wifi": true,
            "bluetooth": false,
            "nfc": true,
            "gps": true
        },
        "testSpecArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(TEST_SPEC_UPLOAD_ID)"
    }
}
```

#### テスト実行結果の取得

`get-run`は単一のテスト実行結果の詳細を取得したいときのAPIで、実行結果の一覧を取得するAPIは`list-runs`を指定することで取得できた。

```shell
% aws devicefarm list-runs --arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) --region=us-west-2    
{
    "runs": [
        {
            "arn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):run:$(PROJECT_ID)/$(RUN_ID)",
            "name": "202210111605",
            "type": "APPIUM_PYTHON",
            "platform": "IOS_APP",
            "created": "2022-10-11T16:06:44.681000+09:00",
            "status": "COMPLETED",
            "result": "FAILED",
            "started": "2022-10-11T16:06:44.681000+09:00",
            "stopped": "2022-10-11T16:20:14.277000+09:00",
            "counters": {
                "total": 3,
                "passed": 2,
                "failed": 1,
                "warned": 0,
                "errored": 0,
                "stopped": 0,
                "skipped": 0
            },
            "totalJobs": 1,
            "completedJobs": 1,
            "billingMethod": "METERED",
            "deviceMinutes": {
                "total": 11.22,
                "metered": 4.49,
                "unmetered": 0.0
            },
            "appUpload": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(APP_UPLOAD_ID)",
            "jobTimeoutMinutes": 150,
            "devicePoolArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):devicepool:$(PROJECT_ID)/$(DEVICEPOOL_ID)",
            "locale": "ja_JP",
            "radios": {
                "wifi": true,
                "bluetooth": false,
                "nfc": true,
                "gps": true
            },
            "testSpecArn": "arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(TEST_SPEC_UPLOAD_ID)"
        },
        {
        ...

```


### Jnekins CI

https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/continuous-integration-jenkins-plugin.html

https://qiita.com/oh_rusty_nail/items/b59aca5f7ec54c51c663#jenkins%E5%81%B4%E3%81%AE%E8%A8%AD%E5%AE%9A

https://tech.mobilefactory.jp/entry/2020/12/23/000000


上記の記事などを参考に次の設定でJenkinsからDvice Farmと連携してCI対応できる。
1. Device Farmのアクセスを許可するIAM(Identity and Access Management)を準備
1. JnekinsでDevice Farmのプラグインをインストール
1. 設定画面に入るとDevice Farmの設定フォームが追加されているため、ダウンロードした`user_credentials.csv`からAKID(Access key ID)とSKID(Secret access key ID)を取得してその設定フォームに記入する
1. ジョブの設定から作成済みのDevice Farmプロジェクトを選択できるようになる。


<img width="350px" alt="スクリーンショット 2022-10-02 12.31.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/bfdaaa83-ed3a-4007-a920-94ce40f79012.png">

<img width="470px" alt="スクリーンショット 2022-10-02 13.01.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4268073e-e3d6-d08f-d636-09dea6ed01f2.png">


#### 注意1: セキュリティ問題

https://plugins.jenkins.io/aws-device-farm/

やJnekins上で警告が出ているとおり、現在2022/10/01時点でDevice FarmのJnekinsプラグインが`unresolved security vulnerability affecting`となっているため、使用する際には十分検討すること。

対策としては、Jenkinsを起動しているマシンにアクセス制限をかけたセキュアなネットワーク環境にする。
または、一旦プラグインの使用を止めてAWS CLIをJnekinsマシンにインストールして、ジョブのビルド設定でシェルの実行から[aws devicefarm](https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/cli-ref.html)を使って連携することでセキュアなCI対応ができる。


#### 注意2: Locale設定問題

Device FarmのコンソールからだとDevice Locale(端末の国籍設定)を変更できるもののJenkinsプラグインの設定ではLocaleの変更が用意されていない。

https://github.com/awslabs/aws-device-farm-jenkins-plugin/issues/99

上記のIssueがあったため試しに手元にMavenビルドできる環境を準備してhardcodeされてる箇所を変更して、`make clean compile`してできたプラグインをJenkinsに入れて使ってみても変更されなかった。

そのためデフォルトの`en_US`以外を設定してテストを実行したい場合は、プラグインの使用をやめてシェルスクリプトで実行に変更して、上記の`$ aws devicefarm schedule-run`を用いることで実現できる。
が、アプリファイル・`test_bundle.zip`・TestSpecをアップロードする`create-upload`の実行設定とそのレスポンスに入っているarnを以下のように取得して、`schedule-run`で指定するJsonに設定するshell操作が必要になるため少し手間がかかる。


```sh
% aws devicefarm create-upload \
    --region=us-west-2 \
    --project-arn arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):project:$(PROJECT_ID) \
    --name build/PageBasedSample.ipa \
    --type IOS_APP \
    | jq '.upload.arn'
"arn:aws:devicefarm:us-west-2:$(ACCOUNT_ID):upload:$(PROJECT_ID)/$(IOS_APP_UPLOAD_ID)"
```


## 料金

<img width="650px" alt="請求管理コンソール - us-east-1.console.aws.amazon.com.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/52af5ca2-6055-5d56-b4fc-bec8b407ebc7.png">

7, 8月で多く使用したことで途中から1000分無料枠を使い切って従量課金対象に切り替わったのでざっくり計算してみた。今回の他に前にもDevice Farmを別件で少し使ったことがあるため誤差はその分なのか。

<img width="350" alt="スクリーンショット 2022-09-13 14.50.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/3e2cd8d5-71e6-c999-6a41-b0a7d764e724.png"> <img width="350" alt="スクリーンショット 2022-09-13 14.50.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/d2151a30-83b1-cdd4-26d4-9ac96e4c9b1d.png">

Airtestの対応でテストが正常に終わらず実行前に設定したタイムアウトも機能せず実行されたままの状態になるケースがあり、その場合無駄に使用時間が増えて料金も増えてしまうことがあった。
また、device poolで設定したデバイス数 × １テスト実行の使用時間が計算されるため、調査や初回の導入対応の際は1,2つのデバイス数を設定とよいだろう。

<img width="350" alt="スクリーンショット 2022-09-22 12.49.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/64720ce7-f798-1216-0cc9-b71b2d694db4.png">
<img width="350" alt="スクリーンショット 2022-09-22 12.51.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4567d0e3-932e-4902-e266-1285da43a63e.png">

従量課金に切り替わった次の月でメンテナンスのため少し使用してみたところ上記のような料金結果になっていた。
使用時間が約５分近いものの実際には約3分使用した分の料金が計算されており、おそらく実行したテストの時間分ではなく、そのテスト内でデバイスを使用した時間を裏でカウントされたものが約3分だったのではないかと考えられる。