NTTドコモR&Dの技術ブログです。

MagicPod × FlutterでAndroid/iOS自動テストを一本化して自動化コストを約50%削減した話

この記事は、NTTドコモアドベントカレンダー2025およびMagicPodアドベントカレンダー2025の13日目の記事です。

1. はじめに

初めまして!NTTドコモ 第一プロダクトデザイン部の上田史貴です。
普段は映像再生ライブラリの開発や、映像配信サービスLeminoのテスト自動化を担当しています。
この記事では、E2Eテスト自動化ツールMagicPodを使ってFlutterアプリのテストをAndroid/iOSで共通化し、テストケース作成コストを約50%削減した実践プロセスを紹介します。

2. 前提

想定読者

  • FlutterでAndroid/iOSアプリを開発している
  • MagicPodでE2Eテストやリグレッションテストの自動化に取り組んでいる/取り組もうとしている

MagicPodとは?

MagicPodは、ノーコードでE2Eテストを自動化できるツールです。直感的な操作でUIを選択し、豊富なコマンドを使ってテストに必要な操作を自動化できます。 最近では、テストケースの作成を自動化する機能もリリースされ、生成AI技術によって自動化の効率をさらに向上できることが期待できます。

3. 背景

Leminoはモバイルアプリ、ウェブブラウザ、スマートテレビなど多様なデバイスに対応しており、毎回のリリースで大量のリグレッションテストを手動実施していました。この作業によってコスト増大だけでなくリリースまでの期間が長引き、サービス品質にも影響を与える状況になっていました。特に競争が激しく迅速な改善が求められる映像配信サービスにおいては、テストが大きなボトルネックになっていました。そこで2025年にテスト自動化チームが発足し、MagicPodを活用したリグレッションテストの自動化を進めています。

4. 課題

MagicPodでモバイルアプリ向けテストケースを作成する際、以下のような課題がありました。

UI要素が正しく認識されない

Flutterアプリの場合、MagicPod (正確にはその裏で動いているAppium)の仕様上、複数のウィジェットが1つのUI要素として認識されます。そのため、特定のUI要素のタップや値取得ができず、テストケースの作成に大きな支障がありました。

MagicPodによるキャプチャ画面
MagicPodによるキャプチャ画面。赤枠内のサムネイルや作品タイトルなどが単一のUIとして認識されています。

さらに、ビルドごとにUIツリー構造が変わってしまうため、作成時に指定したロケータが実行時に認識されなくなる問題も頻発していました。

Android/iOSで別々のテストケースが必要になる

モバイルアプリのテスト自動化では、同一シナリオであってもAndroid/iOSそれぞれにテストケースが必要になることが課題です。 作成コストが2倍になるだけでなく、UI変更等で修正が必要になった場合、両方を修正しなければならずメンテナンスコストの増大にもつながります。
LeminoアプリはFlutterで開発しており、UIは両OSで共通化されています。本来であればテストケースも共通化したいところですが、AndroidとiOSでロケータ (UI要素の識別子)が異なる (それぞれandroid.widgetXCUIElement)ことが障壁になっていました。

これらの課題を解決するため、画面上の各UI要素にユニークIDを付与し、両OSで同じロケータを利用できるようにすることでテストケースを一本化しました。具体的な方法を次章で説明します。

5. 実装方法

ユニークIDを使うためには、アプリ側でIDを付与し、MagicPodがそのIDを参照する設定が必要になります。

アプリ側でユニークID付与

ID付与にはSemanticsウィジェットのidentifierプロパティを利用しました。ユニークIDの付与についてはMagicPodヘルプページ1を参考にしました。semanticLabelやSemanticsウィジェットのlabelを利用する方法もありますが、どちらもスクリーンリーダーの読み上げ対象になることがユーザー影響につながる懸念があったため採用しませんでした。

UI要素をウィジェットごとに認識されるようにするには、Semanticsウィジェットで切り出したいウィジェットをラップします。 また、Android/iOSで同じIDとするために、SemanticsウィジェットのidentifierにIDを付与します。ここで付与したidentifierはMagicPodで提示されるロケータとして使用できるようになります。

child: Semantics(
    identifier: '<パッケージ名>:id/<任意の文字列>',
    child: ElevatedButton(
        ...
    ),
)

MagicPod側でのロケータ共通化

こちらのヘルプページ2を参考にしました。
ID付与によって、以下のようなXPathがロケータとして提示されます。それぞれresource-id属性、name属性の値が付与したユニークIDとなっています。

  • Android: xpath=//android.view.View[@resource-id='<パッケージ名>:id/<任意の文字列>']
  • iOS: xpath=//XCUIElementTypeStaticText[@name='<パッケージ名>:id/<任意の文字列>']

しかし、このままではAndroidとiOSでクラス名や属性が異なります。共通のロケータとするには、以下のようにクラス名をワイルドカード (//*)に置き換え、属性部分に共有変数を利用することでOSごとに切り替えられるようにします。

変更前 (Android) 変更前 (iOS) 変更後 (共通)
クラス //android.view.View //XCUIElementTypeStaticText //*
属性 @resource-id @name ${textAttribute}

解説

  • //*: 画面内のすべての要素を対象にするXPath構文
  • ${textAttribute}: textAttributeは共有変数で、テスト実行時にプレースホルダ内へ動的に値が挿入されます。Androidではresource-idを、iOSではnameを設定しておきます。共有変数の設定方法はヘルプページ3を参照してください。

最終的なロケータがこちらです。書き換えた後のロケータを利用してテストケースを作成すれば、OS判定が自動的に行われ、AndroidとiOS両方で動作するようになります。

xpath=//*[${textAttribute}='<パッケージ名>/<任意の文字列>']

6. 効果

ユニークIDを用いたテストケース共通化により、コスト (時間)・品質の両面で効果が得られました。

コスト面

テストケース作成コスト削減
  • テストケース作成数が約50%削減
  • 作成スピードの上昇:ユニークIDによってロケータの試行錯誤が不要に
メンテナンスコスト削減
  • UI変更などによる修正の手間が約50%削減
  • ユニークIDを付与したことでIDが不変になり、テスト失敗率が低下
  • 失敗率低下により、失敗原因調査・修正の手間も減少
レビュー・運用効率化
  • OSごとにテストケースをレビューする必要がなくなった
  • テストケースのフォルダ構成がシンプルに

品質面

テストケースの一貫性が向上
  • OSによって異なる処理で実装してしまうリスクがなくなり、テストケースの一貫性が向上

7. 注意点

XPathは実行速度が遅い

XPathでは他のロケータと比較すると要素検索に時間がかかります。MagicPod社によると、Accessibility IDやiOS Class Chainと比較すると約4倍の時間がかかるとのこと4。上記のような効果よりも実行時間を優先する場合、今回のアプローチがベストではない可能性もあります。ただ、MagicPodでは並列実行なども可能なので、実質の実行時間を短縮する工夫はできるかと思います。

8. 開発チームの協力がなければ実現できなかった話

余談ではありますが、重要なポイントです。
ID付与はソースコードに手を入れる必要があるため、テスト自動化チームだけでは実現できませんでした。そこで最初に開発チーム向けに説明会を実施し、課題や効果を共有した上で実装を依頼しました。実装段階では、開発チームからID付与案をいただき、それをレビューする流れを繰り返すことで実装を進めていきました。 他にも多くの開発案件がある中、優先度を上げて対応いただいたことでスムーズにテスト自動化を進めることができました。 今回紹介した方法を実践したい方は、開発チームに相談してみてください。

9. まとめ

本記事では、FlutterアプリのE2EテストをMagicPodでAndroid/iOS共通にする手法を紹介しました。画面上のUI要素にユニークIDを付与することで、両OSで共通のロケータを利用可能にしました。これによりテストケース作成コストを約50%削減するとともに、メンテナンスコスト削減やテストの一貫性向上も実現できました。

おまけ:LeminoでのMagicPod選定理由

  • 利用料金が安い: Leminoでのユースケースをもとに想定利用料金を概算したところ、他のツールと比較して利用料金が4分の1でした。
  • 対応環境の幅広さ: ユーザーの環境に近い条件でテストするため、ローカル実機でテスト可能かを重視しました。クラウド/ローカル実機、モバイルアプリ/Webブラウザすべての組み合わせに対応しているのがMagicPodでした。
  • 相談しやすい: 問い合わせフォームやSlackで担当者さんと気軽にコミュニケーションが取れます。エンタープライズプランではオンライン会議で機能や運用に関する詳しい相談ができるのも魅力です。
  • 生成AI活用機能: テストケース作成を自動化してくれるAutopilotや外部AIエージェントとの連携が可能になるMCPサーバー (ベータ版)がリリースされ、ツールとしてさらに成長が見込めます。私たちのチームでも早速これらの機能を利用しており、テストケース作成やメンテナンスの手間を削減できると思っています。

Leminoアプリにおけるテスト自動化の効率向上