waveさんの技術日誌

wave1008の日記の新館です。

モバイルアプリ用E2Eテストツール fleetest [βテスト中]

βテスト中だけどちょっとずつ発信していくよ!

fleetestとは?

fleetestはAI時代のモバイルアプリ用E2Eテストツールです。

github.com

fleetestのコンセプトとは?

コンセプトはPPAPです。

Pen と Pineapple と Apple と Pen が合体したのが PPAP

Macbook と Mac mini と iPhone と Android が合体したのが fleetest

そして合体したのだから当然パワーアップする。

そういうことです。

もう少しちゃんと説明して

はい。すみません。

端的に言うと、AIフル稼働で作った ぼくのかんがえたさいきょうのテストツール です。

あ、まじめにやります。具体的には以下です。

Mac専用

サポートするのはMacだけです。割り切りました。割り切りの美学です。

WindowsとLinuxはサポートしません。 Androidアプリだけを開発している皆様、申し訳ございません。

Mac専用にすることで、ANE(Apple Neural Engine)による機械学習の機能、OCRの機能、FM(Foundation Model)の機能などをフル活用し、テストの精度を向上させるために活用しています。

iOS/Android対応

はい。iOSとAndroidの両方に対応しています。

最新のiPhone Duoにも対応しています。iOS Simulator がバグだらけでどうしようもないですけど、それはAppleの問題でございます。

主要なアプリケーションプラットフォームをサポート

iOSネイティブ、Androidネイティブ、Compose Multi Platform、Flutter、React Native をサポートします。

実際のところどれくらいカバーできているかは検証が難しいのですが、 自作のテスト用アプリでできるだけ多くのパターンをテストしています。

AIを使って延々と探索的テストと不具合修正を繰り返し、問題を潰してます。

自動整定によりツール本体のフレーク要因を可能な限り排除

同期はツールが自動的に行うため、原則としてwaitは書く必要はないです。自動整定で対応できない場合はwaitを書けます。

並列実行でマシンが高負荷になった場合も問題が発生しないように、日々改善を繰り返しています。

単体で速い

どのモードでも自動整定により待ちに無駄がないので速いです。 iOSはinapp-boostモード(デフォルト)を使うとさらに速いです。 Androidは元々速いですが、gRPCを使っているのでさらに速いです。

並列化して速い

コアがたくさんあるプロセッサーのMacを使っているのに、テストは1度に1デバイスしか実行できないなんて残念ですよね。 fleetestはメモリが許す限りCPUを遊ばせずに働かせます。 スケジューリングも賢いです。いや、AIが作ったんですが。

マシンを合体して拡張・並列度アップ

これですよ。これ。男のロマン。

合体、拡張、パワーアップです。

Mac + Mac + iPhone + Android = fleetest です。

※変形はしません。

AIでMCPを使ってテストコードを作成

テストコードはClaude CodeやCodexのようなAIアシスタントに依頼して作らせます。 AIアシスタントはMCPでアプリを操作しながらアプリの画面の構造を理解し、適切なテストコードを実装してくれます。

テストベース(設計書やテスト仕様書など)をAIアシスタントに渡せば、その内容に沿ってテストコードを作ってくれます。 テストベースがない場合でも、「基本ルートのテストを作成して」と依頼すれば、空気を読んで作ってくれます。 作った結果が気に入らなければ、チャットで修正指示します。

テスト実行時は完全ローカル実行・課金なし

テストを作るときはAIアシスタントを使いますが、テストを実行するときはクラウドのLLMは使わず、完全にローカル(LAN内)で実行されます。 クラウドのLLMは使わないのでトークン代はかかりません。

完全ローカル実行ということは・・・ そう、テスト結果を外部に送信しないので、高い機密性が要求される組織でも使えそうですね!

使い方はAIに聞く

使い方は基本、AIアシスタントにチャットで聞けば教えてくれます。迷ったら聞けば良いので、簡単です。

以下のように実行も依頼できます。

  • 最新のiOS Simulatorを3台構成でテストプロファイルを作って
  • profile1を使用してテストを実行して
  • 1時間の探索的テストを実行してバグ出しして
  • テスト結果を分析してレポートにして

AIコーディング時代に自動テストについて思うこと

AIコーディング

人間がコードを書いてレビューしてテストする時代がこんなにあっけなく終わるとは思わなかった。

コードを書くこと自体の面倒臭さ、デバッグの苦しさを乗り越えて、思い描いたソフトウェアが動いた時の達成感 のようなものは失われた。

一方で、今まで考えもしなかったことが安価(トークン代+電気代)で実現できるようになった。

気持ちを入れ替えて、これからはAIに全ベットします。

OSSと品質

従来人間による手作業では手間がかかりすぎて諦めていたことの一部が AIを使うことでできるようになった。 特に品質の分野はそうだ。

OSS(オープンソースソフトウェア)はユーザー数が多いものが品質面で安心とされてきたが 現在はソフトウェア基盤はAIで自作した方が品質やパフォーマンスを確保でき 外部ツールへの依存を減らせることができるので強いと思えるようになってきた。

Appium

AppiumはモバイルアプリのE2E自動テストをOSSとしてリードしてきた先駆者であり、リスペクトされるべきプロジェクトだ。 しかし、Appiumの活用を散々研究してきた身としては、AIコーディング時代には今までのAppiumの路線の延長線上に未来はないと思う。

Java/JavaScript/Python/C#など自分の好きな言語でテストコードを書けるという特徴は AIでコードを書く時代には害はあっても利点はない。 あえて選ぶとしたら、配布に都合が良いものや、パフォーマンスが出るものを選べば良い。 コードの書きやすさは評価軸に現れない。

Appiumを使う際の悩みとしては

  • 遅い(特にiOS)
  • 不安定(フレーク、システムエラー)

というものがある。 メジャーなOSS製品は第一線の開発者たちが洗練させてきたものだろうし、それでも悩みが解消しないのだから、 本質的にこれらの問題は改善が困難なのだろうとずっと思ってきた。

ふと思いついて、モバイル用テストドライバーをAIで自作してみた。 AIと対話しながら作業した結果、Appiumよりも圧倒的に高速で、フレークも原理的に抑えたものをあっさり得た。

なんなんだこれはと思った。

結局、上記のAppiumの悩みはアーキテクチャの欠陥から来ていることがわかった。 過剰な汎用性、中継するプロセスの多さ、waitを前提とする同期の仕組みの脆弱さなどが、遅さと不安定さの原因となっていのだと理解した。 でも実際は直せるんですよ。これらの問題の大半は。ただ、ソフトウェアの互換性を維持しないといけない責任を負った製品は、そのことに気付いたとしてもずっと直せないまま放置される場合が多い。 アーキテクチャの欠陥を直すのは互換性の放棄につながるので、過去を否定しなければならい。それには勇気とリソースが要る。

Shirates

拙作のShiratesはAppiumをラップしたテストドライバーなので、Appiumの欠点はそのまま継承することになる。 後付けの機構で不安定さはある程度カバーしたものの、とても遅いテストツールのままである。

余計なものを捨て、極端に振りったテストドライバーを作る

Appiumの利用経験とShiratesの開発経験からモバイルアプリのテストツールに関する知見を得ることができた。 AI時代が到来した今、新しくドライバーを作るなら前提はこうだ。

  • macOS専用とする
    • WindowsとLinuxはiOSのテストができないので、カバーしない(テスト対象OSを減らすことで開発リソースを温存する)
  • 実装言語はSwiftにする
    • macOSを前提とした場合、Javaのようなクロスプラットフォーム環境を選ぶ必然性はない。Swiftを選択することでシステムプログラミングが可能になり、macOSの能力を最大限に引き出せる。特に、Apple Foundation ModelのようなOSのAPIを利用するにはSwiftが必ず必要となる
  • アプリケーションはクロスプラットフォームを目指す
    • iOSネイティブ、Androidネイティブに加え、Compose Multi Platform、Flutter、React Nativeをカバーする
    • 専用開発したSwift DSLを使うことで、同じテストコードで全プラットフォームのコードを書けるようにする
  • 速度と安定性の最大化を目指す
    • アーキテクチャと実装の両面で限界までチューニングを行う(AIと徹底的に対話する)
  • AIネイティブのユーザーインターフェース
    • Claude CodeやCodexなどのインターフェースから指示してAIコーディングやツール操作をすることを前提とする
    • AIがテストツールを手足として使えるようにCLIやMCPを用意する
  • テストの並列実行を民主化する
    • テストを並列実行することはE2Eの自動化では必須の要素だが、OSSを志向する開発者にとっては管理を含めて実運用に耐え、かつ安価な製品がない。これを提供することでテスト並列実行の民主化を促す
    • macを追加することで並列数を増やせるようにする(合体して機能強化できるガジェットは男のロマンである)
  • テスト実行の状態を記録し、改善可能とする
    • テスト結果だけでなく、実行時間、フレーク発生などのイベントを記録しAI分析・改善を可能とする
  • クラウド対応はしない
    • ローカルネットワークで、自前のmacとスマホだけでシステム構成できる製品とする
    • Claude CodeやCodexはクラウドサービスへの接続が必要だが、代わりにローカルLLMを使用すれば外部へのデータ送信が発生しないセキュアな運用が可能

Shirates/Vision for macOS クイックスタート(動画)

Shirates/Vision for macOS クイックスタートの動画を作成しました。

youtu.be

  • Text to Speech はGoogle AI Pro

  • バックグラウンドミュージックは SUNO

で作成してみました。

Text to Speechは同じ声でも生成するたびに声色が微妙に変わってしまうのでイマイチ。一貫性ってやつの問題かな。他にいいのがないかな。(ずんだもん?)

SUNOはProプランに入りましたが、使いきれないくらいクレジットが付与されるので 動画毎にオリジナル曲を生成できそう。 (月に500曲も生成できるとか、何ソレ)

Shirates/VisionをNotebookLMのお二人に語ってもらいました

Notebook LM を使い始めました。

Shirates/Visionのドキュメントを読み込んで音声データを作成したらいい感じに語ってくれましたので これを元に動画を作成してみました。

ldi-github.github.io

youtu.be

動画のキャプションはPremiere Proの自動文字起こし機能を使ってつけました。変換がおかしなところは手動で修正しましたが、全部手で作成するより圧倒的に楽でした。

音声解説の内容は微妙な箇所が無いわけではないですが、だいたい合ってると思います。

すごいなこれ。

Shirates/Vision[Beta] コンピュータービジョンによるモバイルアプリ自動テストツール

モバイルアプリの自動テストツールShiratesがコンピュータービジョン駆動になって生まれ変わりました。ベータ版が公開中です。
Shirates/VIsion

Shirates/Visionとは

Shirates/Vision はmacOSのVision Frameworkを活用したコンピュータービジョン(CV) 駆動のモバイルアプリテストフレームワークです。

真のマルチプラットフォーム

CV駆動なのでAndroidとiOS上の全てのアプリケーションプラットフォームでテストを実行できます。

  • Androidネイティブ
  • iOSネイティブ
  • Flutter
  • Compose Multiplatform
  • 他

キーテクノロジー

  • AI-OCRによるテキスト認識
  • 機械学習による画像分類およびマッチング

直感的なAPIと容易なコンフィグレーション

  • 面倒な構成(Shirates/Classicにおける[画面名].jsonなど)を行うことなくモバイルアプリの操作や検証ができます
  • 必要なことはスクリーンショット(画面およびアイコン)をキャプチャしてディレクトリに格納し、その画像を利用してテストコードを実装し、テストを実行することだけです

iOSにおける顕著なパフォーマンス改善

コンピュータービジョン駆動のAPIはDOMへのアクセス(この処理が特にiOSでは非常に遅い)をバイパスします。 Shirates/Vision のパフォーマンスは旧バージョン(Shirates/Classic)と比較してiOSにおけるパフォーマンスが劇的に改善されています。

Androidにおける安定性改善

Shirates/Vision の安定性は旧バージョン(Shirates/Classic)と比較して改善されています。

Shirates/Classic

Shirates/Classic は古いバージョンです。従来は単にShirates と表記していました。appiumを使用したDOMアクセスによる従来型の方式によるテストフレームワークです。
Shirates/Vision はShiratesの新しいバージョンです。

Compose MultiplatformとAppiumの相性の悪さに絶望している → 今は希望を持っている

このチュートリアルを参考に Compose Multiplatformでアプリを作って Appiumのテストをやってみようと思ったんですよ。

www.jetbrains.com



Android, iOSそれぞれのアプリの起動ができて おおっと思いました。

で、Appium Inspectorで中身をのぞいてみたんですよ。 そうしたら、iOSアプリのほうですが、中身に意味のあるものが無いんです。

<?xml version="1.0" encoding="UTF-8"?>
<AppiumAUT>
  <XCUIElementTypeApplication type="XCUIElementTypeApplication" name="ComposeDemo" label="ComposeDemo" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
    <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
      <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
        <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
          <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
            <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="393" height="852" index="0">
              <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="59" width="393" height="759" index="0">
                <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="59" width="393" height="759" index="0">
                  <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="false" accessible="false" x="0" y="59" width="393" height="759" index="0"/>
                  <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="59" width="393" height="759" index="1">
                    <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="59" width="393" height="759" index="0"/>
                  </XCUIElementTypeOther>
                </XCUIElementTypeOther>
              </XCUIElementTypeOther>
            </XCUIElementTypeOther>
          </XCUIElementTypeOther>
        </XCUIElementTypeOther>
      </XCUIElementTypeOther>
    </XCUIElementTypeWindow>
    <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="false" accessible="false" x="0" y="0" width="393" height="852" index="1">
      <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="false" accessible="false" x="0" y="0" width="393" height="852" index="0">
        <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="false" accessible="false" x="0" y="0" width="393" height="852" index="0"/>
      </XCUIElementTypeOther>
    </XCUIElementTypeWindow>
  </XCUIElementTypeApplication>
</AppiumAUT>

XCodeで作成したiOSアプリなら [Clic me!]の部分が XCUIElementTypeButton に [Compose: Hello, iOS 17.2!] の部分が XCUIElementTypeStaticText になるはずなんです。 でも、それらが存在していない。

これの意味するところは、Appiumのロケーターで要素を指定することが不可能ってことです。 つまり、Compose Multiplatformで作成したiOSアプリは、Appiumで自動テストすることができない。

困りましたね。 どうしたらいいんでしょうか。

2025.6.26追記

本件、改善したことを確認しました!

qiita.com