アプリリンク（ App Links ）のテストには Maestro が良さそうだった

最近Androidの[アプリリンク（ App Lins ）](https://developer.android.com/training/app-links/)の起動テストする機会がありました。

## アプリリンクについて

まずアプリリンクをサポートするには AndroidManifest.xml を次のようなの構成にします。
```xml
<activity
  android:name=".modules.initial.MainActivity"
  android:screenOrientation="portrait">
  <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
  <!-- アプリリンク用の設定 -->
  </intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="https"/>
    <data android:host="example.com"/>
    <data android:pathPrefix="/restaurants"/>
  </intent-filter>
</activity>
```

上記のアプリリンクは https://exsample.com/restaurants をサポートしています。

見て分かる通り `scheme` `host` `path` とURLを分割して設定しており、pathも次のようにある程度は正規表現を利用することができます。

`android:path`
`android:pathPrefix`
`android:pathSuffix`
`android:pathPattern`
`android:pathAdvancedPattern`

https://developer.android.com/guide/topics/manifest/data-element?hl=ja

## アプリリンクをテストする上で網羅するのは課題

```
// 都道府県ページ 47つあるよ
https://exsample.com/tokyo/detail/
 :
// 市区町村ページ　同じURL階層に存在する
https://exsample.com/tokyo-chiyoda/detail/
 :
```

上のような URL があった場合、都道府県のみアプリリンクにしたい場合 URL の構成上どうしても AndroidManifest.xml にはベタ書きになってしまいます。

```xml
  </intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="https"/>
    <data android:host="example.com"/>
    <!-- 市区町村を対象にしたくないので、47都道府県をベタ書き -->
    <data android:path="/tokyo/detai/"/>
    :
    <data android:path="/okinawa/detai/"/>
  </intent-filter>
</activity>
```

このUIテストを実施するにあたり、47ページもテストすると、かなりコストがかかってしまいます。

## UIテストの種類

Android の UI テストにはいくつかライブラリも存在しています。

* Espresso [link](https://developer.android.com/training/testing/espresso?hl=ja)
Android 公認のテストフレームワーク
* UI Automator [link](https://developer.android.com/training/testing/other-components/ui-automator?hl=ja)
Android 公認のテストフレームワーク
* appium [link](https://github.com/appium/appium)
クロスプラットフォームで利用できるテストフレームワーク
* shirates [link](https://github.com/ldi-github/shirates-core)
内部で appium を使用している統合テストフレームワーク

Espresso や UI Automator は公認のテストフレームワークのため [Firebase Test Lab](https://firebase.google.com/docs/test-lab?hl=ja) でも利用できたりとメリットも大きい反面、導入までにはコストがかかります。

またページのUI・UXは施策を進める中で常に変わっていくもので、リリース毎に常にUIテストを更新していくだけでもコストは大きくなります。

## もう簡単なUIテストは Maestro でよくない？

Maestro https://maestro.mobile.dev/ は、とてもシンプルな UI テストフレームワークです。
```yaml
# flow_contacts_android.yaml

appId: com.android.contacts
---
- launchApp
- tapOn: "Create new contact"
- tapOn: "First Name"
- inputText: "John"
- tapOn: "Last Name"
- inputText: "Snow"
- tapOn: "Save"
```

このように Yaml に `appId` を設定した上で、[コマンド](https://maestro.mobile.dev/api-reference/commands)を記載し実行すれば、自動的にUIテストが始まります。

今回の課題だったアプリリンクも次のとおりです。
```Yaml
appId: # アプリケーションID
---
# 都道府県
- evalScript: ${output.pref_roman = ["hokkaido","aomori","iwate","miyagi","akita","yamagata","fukushima","tokyo","kanagawa","saitama","chiba","ibaraki","tochigi","gunma","niigata","toyama","ishikawa","fukui","yamanashi","nagano","aichi","gifu","shizuoka","mie","osaka","hyogo","kyoto","shiga","nara","wakayama","tottori","shimane","okayama","hiroshima","yamaguchi","tokushima","kagawa","ehime","kochi","fukuoka","saga","nagasaki","kumamoto","oita","miyazaki","kagoshima","okinawa"]}
- evalScript: ${output.pref_kanji = ["北海道 ", "青森県 ", "岩手県 ", "宮城県 ", "秋田県 ", "山形県 ", "福島県 ", "東京都 ", "神奈川県 ", "埼玉県 ", "千葉県 ", "茨城県 ", "栃木県 ", "群馬県 ", "新潟県 ", "富山県 ", "石川県 ", "福井県 ", "山梨県 ", "長野県 ", "愛知県 ", "岐阜県 ", "静岡県 ", "三重県 ", "大阪府 ", "兵庫県 ", "京都府 ", "滋賀県 ", "奈良県 ", "和歌山県 ", "鳥取県 ", "島根県 ", "岡山県 ", "広島県 ", "山口県 ", "徳島県 ", "香川県 ", "愛媛県 ", "高知県 ", "福岡県 ", "佐賀県 ", "長崎県 ", "熊本県 ", "大分県 ", "宮崎県 ", "鹿児島県 ", "沖縄県 "]}

- evalScript: ${output.j = 0}
- repeat:
    label: 物件一覧（都道府県）ALL
    while:
      true: ${output.j < output.pref_roman.length}
    commands:
        - runFlow:
            file: ./flow_nomarket.yaml # テスト結果をチェックする yaml に引き続き
            env:
              URL: https://www.homes.co.jp/smp/${output.pref_roman[output.j]}/list/
              ASSERT_0: ""
              ASSERT_1: "${output.pref_kanji[output.j]}"
        - evalScript: ${output.j++}
```

Yaml × Scriptベースでのテストケース作成は、そこまで高いテクニカルスキルを必要としません。

### Maestro でアプリリンクのUIテストをする上で良いと思った点

* 導入が簡単
curl でインストールすればOK、あとは Yaml だけ
* 運用コストが低い
Yaml の変更だけでOK
さらに [Maestro Studio](https://maestro.mobile.dev/getting-started/maestro-studio) を活用すれば GUI ベースでテストケース作成ができる
* コンテンツのロードを、ある程度自動的に待ってくれる
* Auto verification をオンにして [openlink](https://maestro.mobile.dev/api-reference/commands/openlink) テストが可能
Android 12 以降デフォルトでブラウザが立ち上がるが、この機能を使えば対応できる

### Maestro の微妙なところ

* インストールは公式にも記載されているが Homebrew が非推奨なのは悲しい
* まだ ASSERT 周りが少ない