こんにちは!ブランドアプリを開発しているAndroidエンジニアのkoguchiです。 今回はブランドアプリ(Android)のWebView/CustomTabsのUIテスト実装におけるAI活用について紹介します。
背景
ブランドアプリとはSTORESのプロダクトの一つで、店舗アプリをノーコードで簡単に作成することができるサービスになります。https://stores.fun/brandedapp
ブランドアプリの開発チームではアプリの品質維持・向上のため昨年からE2Eテストの導入を行っており、AndroidにおいてはEspressoとRobotパターンを使用してUIテストを実装しています。
またブランドアプリは今年からSTORES全社のID基盤への移行を行い、STORESの他プロダクトとの連携を進めています。 連携機能の表示には主にWebViewやCustomTabsを使用しており、ブランドアプリから他のプロダクトをスムーズに利用する体験を目指しています。
これらの取り組みは以前の記事でも紹介しています。
課題
ネイティブ実装のUIと比較してWebViewやCustomTabsのUIテストコードの実装は難易度が一定高くなることはイメージできるかと思います。 そのため連携機能を考慮したE2Eテストの実装にあたり、Espressoで構築した既存のコードベースの中にWebViewやCustomTabsのUIテストを組み込むことに開発コストの面で懸念を感じていました。
また最近ではClaudeCode等のAIコーディングツールを使用することでネイティブ実装の機能開発のスピードは向上していますが、プロダクト外のリポジトリでコンテンツが管理されているWebVIewやCustomTabsの実装ではあまりAIの恩恵を受けることができない状態にありました。
AIを使ったUIテスト実装の改善
上記の課題に対して、アプリの画面を直接AIに認識させる方法で解決を図りました。 表示中のUIを見ながらAIと対話的にやりとりしてテストコードを作成することで実装効率を改善しています。
具体的に利用したツールやアプローチは以下になります。
アプリの画面をAIに認識させるためのツール・開発環境
開発にはClaudeCodeを使用し、アプリの画面の認識にはmobile-mcpを利用しました。 mobile-mcpは主にモバイルアプリのオートメーション用途のMCPになりますが、アプリを操作する上で画面のコンテキストを認識しているはずなので、ClaudeCodeに画面を見せる用途にも使えることを期待して採用しました。
mobile-mcpを利用したUIテスト実装の手順
今回はブランドアプリのログイン画面を題材に紹介します。ログイン画面は全社のID基盤上で提供されておりAndroidからはCustomTabsで表示する仕様になります。
まずは事前にAndroidエミュレータ(または実機を接続)を起動して認識させたい画面を表示しておきます。 そしてClaudeCodeに画面の確認を指示するとmobile-mcpを介して↓のように表示内容を認識してくれます。

あとは認識した表示内容を前提にテスト実装をClaudeCodeに依頼していきます。 今回は↓のように対象の画面のRobotクラスとその実行したい操作を定義した雛形ファイルを事前に用意しておき、TODOコメントをタスクとして指示することでプロンプトの簡略化と意図しない実装の防止を工夫しています。
class LoginScreenRobot { fun inputEmail(email: String) { // TODO: メールアドレスを入力する処理を実装 } fun inputPassword(password: String) { // TODO: パスワードを入力する処理を実装 } fun clickLogin() { // TODO: ログインボタンをクリックする処理を実装 } }
この例のようにシンプルな操作の場合はコメントがなくてもAIが意図を汲んでくれるかもしれませんが、例えば「特定のDOMが出現するまで一定時間待機する」といったような複雑な操作を実装したい場合には有用になるかと思います。
これらにより下記のような実装が得られます。
class LoginScreenRobot { private val device = UiDevice.getInstance(getInstrumentation()) fun inputEmail(email: String) { val emailField = device.findObject( UiSelector().className("android.widget.EditText").instance(0), ) if (emailField.exists()) { emailField.click() emailField.setText(email) } else { throw IllegalStateException("メールアドレス入力フィールドが見つかりません") } } /* 省略 */ }
その後期待した動作の実装になっているのか動作確認をした上で、必要に応じて適宜修正し実装完了となります。
最後に
今回はmobile-mcpを活用したブランドアプリのWebView/CustomTabsのUIテストの実装効率化について紹介しました。 紹介した例ではClaudeCodeへの指示を手動で行っていましたが、今後はカスタムコマンド化するなどしてより簡易に実装できるように仕組み化していきたいと考えています。
このようにSTORESではAIを使った開発環境や業務フローの改善に積極的に取り組んでいます。 もし興味がありましたらぜひ採用サイトをご覧ください。