Maestro とは?
公式ドキュメントの内容
Maestro の導入
前提
- OS: macOS
- Xcode14 以上をインストールしておく
maestro をインストール
前提としてhomebrew
をインストールした上で、以下コマンドを実行してmaestro
をインストールします。(homebrewのインストールは公式ドキュメントを参照)
brew tap mobile-dev-inc/tap
brew install maestro
以下公式ドキュメントを参考にしています。
https://docs.maestro.dev/getting-started/installing-maestro
Maestro で行う UI テストを書く
Maestro Studio による GUI ツールでのテスト作成
Maestro Studio の起動
シミュレーターをあらかじめ起動しておく必要があります。
以下でシミュレーターを起動できます。(またはXcodeでアプリを実行して任意のシミュレーターを起動しましょう)
open -a Simulator
Maestro の UI テストを GUI で作成するツールが、Maestro 側で用意されています。
以下コマンドで、そのツールを立ち上げます。
maestro studio
実行時ログは以下になります。
% maestro studio
Running on iPhone 16 - iOS 18.2 - 566836CA-C153-4F8B-AFEA-FCD9966B1C55
複数のシミュレーターが立ち上がっている状態で、maestro studio
を実行すると、以下のようにどのシミュレータで実行するかを選択することもできます。
% maestro studio
iOS
[1] iPhone 16 - iOS 18.1 - 63E10B92-8C1E-4CC3-97A1-561536C41F7A
[2] iPhone 16 Pro - iOS 18.2 - D2AE3E98-6626-45C2-BDF9-0D1E522385E7
Multiple running devices detected. Choose a device to run on.
Enter a number from the list above:
maestro studio
が立ち上がると、ブラウザの GUI ツールが立ち上がります。
Maestro Studio で動作確認する
試しにあるボタンをタップしてみると、以下のようなポップアップが表示されます。
再生ボタンを押下すると、アプリの画面がボタンを押下した時の挙動をとります。
今回のアプリではボタンを押すと、別画面へ遷移するのでブラウザ上のアプリの画面も画面遷移しています。
また、右画面には先ほど実行したコマンドが表示されています。
このコマンドが、Maestroテストを構成するコマンドになります。
以下のように、直接自分でコマンドを入力してコマンドの動作確認をすることもできます。
ちなみに以下は"Diary List"という文言が画面に表示されているかを検証するコマンドです。
アプリを自動で動作させる様々なコマンドがあるので、一度公式のリファレンスを見ることをお勧めします。
https://docs.maestro.dev/api-reference/commands
Maestro Studio でテストコードを出力する
いろいろいじってみたらコマンドが溜まってきたので、今まで触ってきた操作を自動化してもらえると嬉しいですよね。
Maestro Studioで使用したコマンドは、実際にテストを行うときに使用するymlファイルにエクスポートすることもできます。
例として、まず以下のようにMaestro Studioで画面を操作します。すると右側にコマンドが溜まっていきます。
以下のような画面が表示されるので、"Save"ボタンを押下するとymlファイルがダウンロードされます。
export すると以下のような yml ファイルが出力されます。
appId: null
---
- tapOn: "graph_circle"
- tapOn:
point: "11%,9%"
- tapOn:
point: "14%,14%"
- tapOn:
point: "66%,25%"
UIテストを実行する
作成したテストコード(yml ファイル)を使って、UI テストを実行するには、以下コマンドを実行すれば OKです。
maestro test <ymlファイルのパス>
上記実行時にも、シミュレーターは立ち上げておく必要ありです。
今回は以下のような yml でテストを行ってみます。
appId: <アプリのバンドルID>
---
# 初期状態にする
- clearState
# アプリ起動
- launchApp
- tapOn: "graph_circle"
- tapOn:
point: "11%,9%"
- tapOn:
point: "14%,14%"
- tapOn:
point: "66%,25%"
実行結果は以下のような感じ
失敗したステップがあればその場で中断し、緑のチェックではなく赤のマークがつきます。
Running on iPhone 16 - iOS 18.2 - 566836CA-C153-4F8B-AFEA-FCD9966B1C55
║
║ > Flow
║
║ ✅ Clear state of morimori.Macho
║ ✅ Launch app "morimori.Macho"
║ ✅ Tap on "graph_circle"
║ ✅ Tap on point (11%,9%)
║ ✅ Tap on point (14%,14%)
║ ✅ Tap on point (66%,25%)
║
╭───────────────────────────────────────────────────────────────────────────────╮
│ │
│ A new version of the Maestro CLI is available (1.39.13). Upgrade command: │
│ curl -Ls "https://get.maestro.mobile.dev" | bash │
│ │
╰───────────────────────────────────────────────────────────────────────────────╯
検証方法
UI テストなので、何かしら検証する必要があります。
検証の主な手法としては、特定の要素が画面に表示されているかを確認することだと思います。
Maestro では、assertVisible
というコマンドが提供されています。
例えば、アプリを起動して以下のような画面が表示されるとします。
画面に"表示する日記がありません"という文言が表示されることを検証したい場合は、以下のような yml を書きます。
appId: <アプリのバンドルID>
---
# 初期状態にする
- clearState
# アプリ起動
- launchApp
# 検証
- assertVisible: "表示する日記がありません"
これでmain.yml
があるディレクトでmaestro test main.yml
を実行すると、以下のようにテストが実行され成功します。
Running on iPhone 16 - iOS 18.2 - 566836CA-C153-4F8B-AFEA-FCD9966B1C55
║
║ > Flow
║
║ ✅ Clear state of morimori.Macho
║ ✅ Launch app "morimori.Macho"
║ ✅ Assert that "表示する日記がありません" is visible
║
以下のように、期待する文言を変えるとテストは失敗します。
appId: <アプリのバンドルID>
---
# 初期状態にする
- clearState
# アプリ起動
- launchApp
# 検証
- - assertVisible: "表示する日記がありません"
+ - assertVisible: "表示する日記がありまてん"
Running on iPhone 16 - iOS 18.2 - 566836CA-C153-4F8B-AFEA-FCD9966B1C55
║
║ > Flow
║
║ ✅ Clear state of morimori.Macho
║ ✅ Launch app "morimori.Macho"
║ ❌ Assert that "表示する日記がありまてん" is visible
║
Assertion is false: "表示する日記がありまてん" is visible
assertion 系のコマンドは他にもいくつかあるので、必要なコマンドがないか公式リファレンスで調べてみると良いです。
https://docs.maestro.dev/api-reference/commands/assertnotvisible
https://docs.maestro.dev/api-reference/commands/extendedwaituntil
要素の指定方法について
Maestro でタップ(tapOn
)や指定の要素があるかどうかの検証(assertVisible
)を行うときなど、要素を指定することはたくさんあります(どの要素をタップするのか、どの要素が存在するのを検証するのかなどの用途)
Maestro では要素を指定方法をセレクターと呼び、いくつかの方法を提供してくれています。
公式ドキュメントでは以下方法で指定することができることを提示してくれています。
- tapOn: # or any other command that works with selectors
text: 'Text' # (optional) Finds element with text or accessibility text that matches the regular expression
id: 'the_id' # (optional) Finds element with accessibility identifier that matches the regular expression
index: 0 # (optional) 0-based index of the view to select among those that match all other criteria
point: 50%, 50% # (optional) Relative position on screen. "50%, 50%" is the middle of screen
point: 50, 75 # (optional) Exact coordinates on screen. x:50 y:50, in pixels
width: 100 # (optional) Finds element of a given width
height: 100 # (optional) Finds element of a given height
tolerance: 10 # (optional) Tolerance to apply when comparing width and height
enabled: true # (optional) Searches for view with a given "enabled" state
checked: true # (optional) Searches for view with a given "checked" state
focused: true # (optional) Searches for view with a given "focused" state
selected: true # (optional) Searches for view with a given "selected" state
自分としてはid
にてaccessibility identifier
を使った指定方法が良いと思っています。
理由としては、最もテストが壊れにくい指定方法と考えるからです。
座標指定(point
)だとデバイスのサイズによっては意図した要素を指定できないこともあるので、デバイス依存のテストになってしまいます。
また、表示文言指定(text
)だと、ローカライズしているなどの事情があれば、デバイスの言語設定に依存してしまいます。(ローカライズしていないアプリでも、OS 依存のダイアログなどはデフォルトでローカライズされているので、この問題の影響を受ける)
accessibility identifier
であれば、上記懸念はないので最も壊れにくいテストになると思われます。
yml ファイルを分割する
確認項目が大きくなってくると、yml ファイルが巨大化してくることが予想できます。
それを防ぐために、画面毎などある程度の粒度で yml ファイルを分けられると嬉しいですね。
maestro では yml ファイルから別の yml ファイルのテストを呼び出すことが可能です。
実装例としては以下のような感じ。
appId: <アプリのバンドルID>
---
# 初期状態にする
- clearState
# アプリ起動
- launchApp
# 別のymlファイルを呼び出す
- runFlow:
file: "check_graph.yml"
appId: <アプリのバンドルID>
---
- tapOn: "graph_circle"
- tapOn:
point: "11%,9%"
- tapOn:
point: "14%,14%"
- tapOn:
point: "66%,25%"
触ってみての感想
-
UI テストを書くコストはかなり低いように感じました。Maestro の GUI ツールで自分の期待する操作を行っていると、Export 機能によって自動で UI テストを生成できるので、非開発者でも UI テストを作れそうという気持ちです。
-
クロスプラットフォームに対応したツールなので、iOS と Android で共通で使うことも可能です。
ただ、実際 iOS と Android で完全に同じ UI になることはあまりないなと思っている(OS のダイアログが違っていたり、微妙に画面のフローが違っているのはあるあるかと)ので、
iOS と Android で共通化できるという目的で利用できるのはレアケースでしょう。
もしやるなら、テキストもしくは AccessibilityId を iOS/Android で完全に揃えて、画面の遷移フローなどもすべて同じである必要があると思います。 -
OS で表示される一部画面ではうまく要素を認識してくれない問題に当たったりということがあったので、一部テストが難しい画面もあります。
例えば、HealthKit の権限モーダルは maestro が要素の位置をうまく検出できなくて、テキストや ID での選択ができず座標指定しか使えなかったです、、 -
テストレポートについては、フロー毎(yml ファイルの粒度)に成功したかどうか程度の情報しか出せないので、テストカバレッジなどの高度なレポートは期待できません
-
実機で Maestro を使用することができないので、シミュレーター上で行えるテストしかできません
入門してみての所感として、手軽な UI テストツールではありますが、一部かゆいところには手が届かず複雑なテストには向かないです。
手軽さ重視で自動化できないところは手動で行うことも辞さない場合は、非常に良いツールなのではと思いました。
逆に手動テストをほぼ全て自動化したい、カバレッジをとってどれぐらいケースを網羅できているのかを知りたいといった用途では Maestro は向かないように思いました。
おわり
今回は入門レベルでどんなことができるのか調べてみましたが、他にもできることがあるので応用編の記事を出す頃にはMaestroの感想も変わるかもです。
まだベータ版でしたが、AIの技術を用いた検証のコマンドがあったり、AIにテスト品質を解析してもらうといった機能もあったので、そのあたりはかなり楽しみですね。
https://docs.maestro.dev/api-reference/commands/assertwithai
https://docs.maestro.dev/cli/test-suites-and-reports#analyze