はじめに
はじめまして!まずは軽く自己紹介から!
私はQAエンジニアとして4年目になります。これまで培ってきたテスト実務の経験に加え、昨年からはAirtestとPocoを使用し、自動テストの構築・運用にも携わっています。
テストの効率化においてAirtestを用いた自動テストが効果的だったので、私がアサインされた新規プロジェクトでも導入しようと思いました。その際、既存のAirtestの機能に加え、UIコントロール認識が可能なPocoを新たに導入しました。しかし、テストの実装を進める中で、AirtestやPocoだけでは解決が困難な課題に直面したため、その解決策としてRPC関数(Remote Procedure Call)を採用するに至りました。
この記事では、私がPoco、RPC関数を使用して自動化に取り組む中で得た知見や、気を付けておきたいことを共有していきたいと思います!
環境
・テスト対象のアプリのゲームエンジン:Unity
・python:3.6.6
・Airtest:1.2.17
※執筆時のプロジェクト環境です。Python 3.6系は既に公式サポートが終了(EOL)しており、セキュリティリスクやライブラリの互換性問題があるため、現在はより新しいバージョンが推奨されます
Poco
そもそもPocoとは
Airtestのフレームワークの一つであるPocoは「UIコントロール認識」の能力を拡張するライブラリでテスト対象のアプリが持つUIの階層構造(Unityで言うとヒエラルキーの部分)を取得し、オブジェクトの座標やテキストなどの属性情報をもとに操作ができるため、テンプレートマッチングの弱点を補うことができます。
※Airtestはゲームの自動テスト用ツールです。画像認識、テンプレートマッチングによって特定した座標に対し操作を行います。
テンプレートマッチングとは、画像認識技術の1つでスクリーンショット全体を走査し、画像(テンプレート)とピクセルレベルで最も類似している領域を特定する手法です。
メリット
Pocoは先述したオブジェクトの属性情報を取得できることがメリットです。
- 画像認識とは違い確実かつ正確に操作ができる
画像認識はテンプレートとして用意した画像がスクリーンショット内に複数あった場合、意図していない座標を取得する可能性があります。
しかし、Pocoであればオブジェクトの座標を取得しているため、確実に操作することができます。
また、交換所やミッションなどのリスト化されたものに対して強く、全て順々に操作するなどの繰り返し処理の実装が比較的簡単にできます。 - 保守管理面において優秀
画像認識はテンプレートとして用意していた画像が変更された場合、変更後の画像に合わせてキャプチャし直す必要がありました。
しかし、Pocoではオブジェクトを指定しているのでデザイン変更や画像の差し替えが発生しても、画像にとらわれずコードの修正なしで対応できます。 - 動作確認以外にもテストできる
取得できる情報は座標だけではなく、テキストやオブジェクトの種類といった属性情報も取得できます。
そのため、テキストに表示されればデータの確認や資料との突合確認も可能です。
デメリット
画像認識の強みは補えない
また、実装環境に影響する可能性がある
- 画像認識でできることができない
もちろん視覚的情報を一切取得していないため、画像が入れ変わったり消えていても検知はできません。
ただ、Pocoを使用しても画像認識が使えなくなるわけではないので、テストにあわせた実装をすることが一番です。 - Airtest IDE以外でのコーディングが厳しい
Airtest IDEではオブジェクトツリーを表示する機能がすでに備わっていますが、他IDEでは備わっていないためコーディングする際にかなり苦労する可能性があります。
しかし、個人的にはIDEを跨いででもAirtest IDEを使うことをおすすめします。
コーディングする際に取得したいオブジェクトをオブジェクトツリーからクリックすることで、自動で親子関係やオブジェクト名の重複を避けた取得コードを一瞬で生成してくれます。
オブジェクトが多い環境では意図していないオブジェクトの参照などを避けられ、人為的なコーディングミスがかなり減らせます。
また、オブジェクトの参照ミスに関しては実行しないとわからないという点もあり、IDE間を跨いででもミスした時の時間を含めればコストを低く抑えられるのでは?と感じました。
気を付けておくべきこと
ここからは、実際に私が直面した問題とその対策などを記載していきます
特定条件下のオブジェクトの座標情報がズレている
※3Dのみの可能性があり、環境固有の可能性もある
Canvas外のオブジェクトの座標情報がズレていました。
実際に直面したのは、3Dオブジェクトに対してタッチの操作を行う時です。
いつも通りオブジェクト情報を取得し、クリック動作を実装して動作確認したところ、タッチ位置が明らかにズレていました。
Airtest IDEではオブジェクトツリーで選択したオブジェクトの座標がIDEの画面上に表示されますが、この時点で下記イメージ画像のようにズレていました。

Airtestで表示される座標はUnity基準ではないことから
オブジェクトツリーを取得する際にPocoで操作できる座標に変換するところで、Canvas外のオブジェクトが対応しきれていなさそうです。
この座標ズレの問題は根深そうな問題だったので私は画像認識で妥協して進めました。
オブジェクトの参照は親子関係が深くかつ、検索名が重複してる分だけ処理が遅くなる
オブジェクトツリーの深層にある、かつ同じ名前が複数あると取得する際にかかる時間が長くなりました。
実際にバトル画面でデバッグコマンドを起動させようと、3階層+重複(10以上)しているボタンをクリックする実装をしたところ、1回のクリックに1分以上かかりました。
こちらの対策としてfreeze関数を検討しました。
Pocoはオブジェクトを参照する度に、オブジェクトツリーのオブジェクト全て取得していますが、freeze関数は呼び出した瞬間の情報を1度だけ取得し、ローカルにキャッシュします。
これによりキャッシュした情報を繰り返し使うことで実行速度が速くなり、実際に実行時間は1/2ほどまで減りました。
しかし、担当していたプロジェクトではスクロール動作も必要であったため、動的なUI操作が弱いfreeze関数での実装は諦め、RPC関数で実装しました。
RPC
RPCとは
Remote Procedure Callの略でテストスクリプトからモバイルアプリの内部処理を直接呼び出すことができます。
UIを介さずに動作させることができるので、先述してきた障害にほとんど対応できます。
メリット
だいたいなんでもできる
引数を設定してデータをアプリ側に送ることが可能です。そのためバトルの調整やデバッグ機能を有効化するなどが簡単にできます。
アプリ側の関数で戻り値にJsonデータを入れて、テストスクリプト側で受け取ることが可能です。
Pocoでも取得できない値(テキストのないゲージ表示など)を取得するなど、必要とあれば全て受け取ることができます。
デメリット
エンジニアとの連携が必須
アプリ側の関数を使用するのでエンジニアとの連携が必須です。
アプリ側の実装となるとQAだけの領域ではなくなってしまうので担当のエンジニアとの連携が必須になります。
私は円滑に進めるため、スプレッドシートを設けて連携しました。以下はエンジニアと認識を合わせるために私が設定した項目になります。
■QA側記入欄
- 概要
どういった経緯で何を実装してほしいか テストスクリプト側で渡せる情報など - 使用画面
そのRPCを使用する画面名 - 取得したい内容
どういった値を取得したいか(例:bool型、オブジェクト名など)
■エンジニア側記入欄
- 引数
引数例があると実装しやすい - RPC関数名
RPC名で実行するので - 戻り値例
戻り値のJsonデータ内にあるパラメータ名などを記載いただく - 戻り値備考
「このresponseに"False"があったとき失敗」などを記載いただく
気を付けておくべきこと
ここからは、実際に私が直面した問題とその対策などを記載していきます
RPC関数で実装したものはユーザー動作ではない
RPC関数で動作させたものはユーザー環境では発生し得ない動作になります。
例えば、デバッグコマンドを呼び出して、プレイヤーを無敵にしたり、テスト用にアイテムを一括付与する操作がこれにあたります。
これらの操作は、ユーザーが画面上のボタンをクリックしたり、スワイプしたりといった通常のUI操作を介しておらず、アプリの内部処理を直接実行しているため 、RPCによる操作の結果、予期せぬ不具合が発生したとしても、それはユーザー環境で通常起こり得る事象ではないと捉える必要があります 。
したがって、RPC関数で実装した動作は、機能が意図通りに実行されたか(デバッグ機能が動いたか)の確認には使えますが、その操作自体がユーザーの操作性を担保するテストにはなりません 。
効果
実際にAirtestとPoco、RPC関数を使用して、ライブサービスゲームの「タイトル〜チュートリアル〜自由操作可能なホーム」までの実行を自動化しました。
この自動化により、今まで日々のテスト時に手動で検知していたテストブロッカーなどの致命的な不具合を未然に検知できるようになり、品質が向上しました。また、不具合の未然検知によって、インストールし直しなどの手戻りの工数が0になりました。
その結果、この自動化箇所においては、リリースから現在まで(半年以上)本番環境での不具合を出すことなく運用できています。
まとめ
Pocoが使用できる環境でも、惜しむことなく画像認識も使うべき。
保守管理面でPocoのみを使用することも良いですが、しかし、何よりテストに合わせた実装が肝心だと感じました。
PocoやRPC関数はアプリ側での実装も必要不可欠。
そのため初期段階でのエンジニアとの連携、交流があれば、実装する際にもっとスムーズに進めたのかなと思いました。
今後の課題
AIと一緒に使う
AirtestとPocoだけではやはり柔軟な対応は難しいと感じました。
環境要因(ネットワークエラーなど)で失敗したら諦めるしかないのか?など、勿体無い部分をAIを利用してうまく自動化できないかを突き詰めたいと考えています。
参考
https://qiita.com/tana_hiro/items/6ffefa6daf6df8ca821d
https://qiita.com/mmm_hiro/items/f6776d3458f767cf9d09
https://qiita.com/bearjiro/items/001acb28051519faa125