🤖

Roo CodeにAndroid端末を操作させてUIテストコードを生成

に公開

はじめに

最近、AIエージェントに関する話題を毎日のように見ますね。
今回はMCPのお勉強も兼ねてRoo CodeにAndroid端末を操作させ、UIテストコードを生成してみました。

AIエージェントを用いたUIテストの種類と、今回の方針

大きく、2種類あると思います。

  • テスト実行と、その成功可否判定自体をAIエージェントに任せるケース
  • テストコードをAIエージェントに生成してもらい、テスト実行や成功可否判定自体は従来のUIテストの仕組みを使うケース

将来的には「テスト実行と、その成功可否判定自体をAIエージェントに任せるケース」が主流となる可能性がありますが、現時点では実行速度・テスト結果予測性などの面で「テストコードをAIエージェントに生成してもらい、テスト実行や成功可否判定自体は従来のUIテストの仕組みを使うケース」にも分がありそうです。

今回は既存のUIテストプロジェクトが存在したため、これにAIエージェントでテストコードを足して貰う方針で進めました。

既存のUIテストプロジェクトについて

  • すでにAppium + TypeScriptで記述されたUIテストコードがいくつかあります
  • Page Object Model デザインパターンを導入し、画面ごとに一つのオブジェクトを作成します

実際のプロンプトとテストコード生成例

まず先に、実際のプロンプトとテストコード生成例を紹介します。
APIプロバイダーはOpenRouter、モデルはanthropic/claude-3.7-sonnetです。

app.android.bookTop.spec.ts に、下記のテストを追加してください。

ブックトップの各タブで画面切替できること
・無料マンガタブ
・読み放題雑誌タブ
・ストアタブ
・キッズ読み放題タブ

上記のプロンプトで、下記のテストコードを生成してくれました。
(テストケースは4つ生成してくれましたが、ここではそのうち2つのテストケースを紹介します)

画面遷移できた事の確認のため、遷移後にしか存在しない画面要素が表示されているかをチェックしてくれていますね。

  it('無料マンガタブをタップすると無料マンガ画面に切り替わること (Tapping free comic tab should switch to free comic screen)', async () => {
    // 無料マンガタブをタップ
    await BookScreen.freeComicTab.click();

    // 無料マンガ画面特有の要素が表示されることを確認
    // 毎日無料ランキングが表示されることを確認
    const dailyFreeRanking = await $(
      'android=new UiSelector().text("毎日無料ランキング")'
    );
    expect(await dailyFreeRanking.isDisplayed()).toBe(true);
  });

  it('雑誌読み放題タブをタップすると雑誌読み放題画面に切り替わること (Tapping magazine tab should switch to magazine screen)', async () => {
    // 雑誌読み放題タブをタップ
    await BookScreen.magazineTab.click();

    // 雑誌読み放題画面特有の要素が表示されることを確認
    // 女性ファッションカテゴリが表示されることを確認
    const womensFashionCategory = await $(
      'android=new UiSelector().text("女性ファッション 20代~")'
    );
    expect(await womensFashionCategory.isDisplayed()).toBe(true);
  });

テストコード生成の事前準備

元々、GitHub Copilot Agentなどでも単純にテストコードを生成する事は実現できていました。
しかし、実際に端末を操作して生成したテストコードでは無いため、存在しないUI要素をクリックしたり表示チェックするコードが生成される事などがありました。

そのため、今回は

  • (今話題の)MCP経由でAIエージェントにAndroid端末を操作させる
    • UI要素をタップして画面遷移
    • UI要素をリストアップ・画面スクショ撮影して内容を把握
      • 把握した内容をテストコード生成時に用いる
  • テストコード生成を楽にするルールの整備

をおこないました。

MCP経由でAIエージェントにAndroid端末を操作させる

https://github.com/modelcontextprotocol/servers から見つけた、
mobile-mcp を利用しました。

https://github.com/mobile-next/mobile-mcp

  • アプリのインストール
  • アプリの起動
  • 端末の一覧表示
  • UI要素の一覧表示
  • 画面のタップ・スワイプ

などができる、優れものです。
これで、MCP対応のRoo CodeなどでAndroid/iOSの実機やエミュレーターなどを操作できます。

Androidの場合はUI要素としてテキストが含まれない不具合があったので、PRを作成してマージしてもらいました。
https://github.com/mobile-next/mobile-mcp/pull/33

mobile-mcpはスクショも撮影できるのですが、Roo CodeやClineではうまく受け取れません。Claude Desktopではスクショ取得できるので、ホスト依存の問題なようです。
スクショ自体はADBで撮れるので、ルールで「スクショ撮影はADBを使用」と指示しました。

テストコード生成を楽にするルールの整備

https://github.com/mizchi/ailab/blob/main/.clinerules を少し参考にさせて頂き、作成しました。

(一部省略していますが)作成した .roorules は下記です。

# 重要

- ユーザーはテストコード生成のため、コーディングを依頼します
- 3 回以上連続でテストを失敗した時は、現在の状況を整理して、ユーザーと一緒に解決方法を考えます
- 現在のコンテキストに応じた処理は苦手なので、コンテキストが不明瞭な時は、ユーザーに確認します
- テスト追加を依頼されたら、後述の「テスト追加について」に従い、テストコード生成とテスト実行、テスト失敗時のテストコード修正をおこないます
  - 特に「テスト追加の流れ」には、必ず従って下さい
  - 必ずテスト結果を確認し、テストに失敗した場合はテストコードを修正して下さい
  - 必ず、タスクの終了前にテストは実行して下さい

# 概要

- このリポジトリは Android アプリと iOS アプリの自動化テストリポジトリです
- Page Object Pattern を使用します

# テスト対象のアプリについて

## タブについて

- ビデオ/ブック/検索/ライブラリ タブがあります
- アプリ起動時には、ビデオ or ブックタブを開くます
  - 前回、アプリ終了時に開いていたタブを開きます
- アプリウインドウの横幅に応じて、Bottom Navigation が非表示となり、代わりに Navigation Rail を表示します

### ブック タブ内の画面について

- ブック タブ選択時に表示される画面は book top です
- book top 上部のタブをタップして遷移する画面は、無料マンガ Top/雑誌読み放題 Top/ストア Top/キッズ読み放題 Top があります

# テスト追加について

## テスト追加の流れ

1. MCP を使用して Android/iOS 端末を操作し、画面遷移や表示 UI 要素を把握します
2. 上記で把握した内容と既存のテストコードを参考に、既存の Page Object を使用(必要に応じて Page Object を修正・追加する)して、テストコードを生成します
3. 生成したテストコードを Android/iOS 端末で実行し、テストが通ることを確認します(もし、テストが失敗した場合はテストコードを修正し、再度テストを実行します)
4. テストが成功するまで、テストコードの修正とテストの実行を繰り返します

## テスト追加の注意点

### 画面遷移が成功したかどうかの確認について

必ず、「画面遷移後だけに存在する UI 要素」が表示されている事を確認して下さい。

NG 例:

// キッズ読み放題タブをタップして画面が切り替わることを確認
await BookScreen.kidsTab.click();
await driver.pause(1000);
expect(await BookScreen.kidsTab.isDisplayed()).toBe(true);

上記の例は、画面遷移前にも存在する BookScreen.kidsTab を、画面遷移後に存在する事を確認しています。これは NG です。

MCP やスクリーンショットを使用して画面遷移前後に表示されている UI 要素を把握し、
画面遷移後に「画面遷移後だけに存在する UI 要素」が表示されている事を確認して下さい。

# スクリーンショットについて

## Andriod

- MCP でのスクリーンショット撮影は失敗します
- 代わりに、adb でスクリーンショットを撮影して下さい
  - 撮影した画像ファイルは screenshots/ に格納して下さい
  - タスク完了後、撮影した画像ファイルは削除して下さい

いくつかのセクションについて、補足します。

重要

テスト追加の流れを無視する事があったので、守るように指示を追加しています。
また、テストコードを生成したただけでタスク完了する事があったので、必ずテスト実行する事を念押ししています。

画面遷移が成功したかどうかの確認について

このセクション追加前は、画面遷移前後の両方に存在するUI要素をチェックして、「テストOK」と判断するテストコードが生成されていました。
具体的なNG例を出して、「画面遷移後のみに存在するUI要素」でテストの成功可否を判断するよう、指示しています。

まとめ

mobile-mcp + ルール整備により、簡単なプロンプトで端末操作・テストコード生成・実行を自動で実現できました!

下記は雑多に思った事です。

  • Roo Code単体ではできないことも、目や手足となるものをMCPで与えてあげると実現できる
  • 既存コードを参照してこれらのスタイルを真似つつテストコード生成は、ほぼ問題無くできる
  • 暗黙知(例:画面遷移後にしか存在しないUI要素で画面成功可否を判断)の明文化が大事
    • どこまでの暗黙知は明文化しなくてOKで、どこから必要なのかが悩ましい

今後はより複雑なテストケースのテストコード生成や、PR作成自体の自動化なども試したいです。

Discussion