Slide 1

Slide 1 text

AirtestとPocoとOpenSTFに よるUnity製スマートフォン向け ゲームの実機自動テスト 環境構築とその利用方法 CEDEC2020 株式会社サムザップ 三森裕史

Slide 2

Slide 2 text

今回の話の概要 ・実機で自動テストをしよう!端末は手元になくてもOK ・「テスト」がないのですぐにできるテストを構築したい ・非プログラマーでも自動化したい ・コロナ禍であってもだれもが同じ端末でチェックできたら良いよね ・甘口セッションです Python知らなくても大丈夫 Androidの話が殆どですが、iOS周りの動向も補足します 2

Slide 3

Slide 3 text

自己紹介 携帯電話やスマートフォンの上で動くゲームを作る人 最近はテストやツール周り等 2017年サムザップ入社 CTO室所属 三森 裕史 過去の発表等 builderscon2018 3

Slide 4

Slide 4 text

株式会社サムザップ  2009年5月 CyberAgent子会社として設立 事業内容  スマートフォンゲームの企画、配信、運営 会社概要 4

Slide 5

Slide 5 text

戦国炎舞 -KIZNA- 2013年4月サービス開始 戦国時代を舞台にしたカードゲーム 運営開始から7年が経過  検証項目の増大が課題 5

Slide 6

Slide 6 text

この仕組みを導入すると何ができるか 実機連打テストの自動化! 6

Slide 7

Slide 7 text

この仕組みを導入すると何ができるか CSVファイル等を利用しノンプログラマでも自動テストが作れる仕組み 7

Slide 8

Slide 8 text

新規タイトルでの運用 ゲームを遊び続けて、エラーが出力された際にSlackへ通知 コンポーネントの中身の値チェック 指定された箇所の動画、スクショ撮影、保存 8

Slide 9

Slide 9 text

今回使用するツールの紹介と説明 9 Airtest Poco DeviceFarmer (OpenSTF)

Slide 10

Slide 10 text

Airtestについて https://airtest.netease.com/ ・NetEase社が開発した画像認識によるテストコードを記述できる環境 とライ ブラリ群 ・IDEによって気軽にテストコードが記述できる ・テストコードはPythonのコードとして保存され、Jenkinsのような各 種CI環 境で実行することが可能 10

Slide 11

Slide 11 text

Airtestについて 11

Slide 12

Slide 12 text

Airtestでできること ・Pythonによるテストコードを記述できる  主に画像認識ベースの処理 ・タッチ、スワイプ等の処理  切り抜いた画像でテンプレートマッチングし、合致した箇所にタップ ・各種assert  画面内に切り抜いた画像と一致する箇所があるか? 12

Slide 13

Slide 13 text

Airtestでできること 13

Slide 14

Slide 14 text

Pocoについて Airtestのライブラリ Unityや各種ゲームフレームワークの UI情報を取得し、Python上で操作 することができる。 14

Slide 15

Slide 15 text

Pocoでできること Unityや各種ゲームフレームワークのUI情報を取得 15

Slide 16

Slide 16 text

DeviceFarmerについて 16 同一ネットワーク下でブラウザごしに実機を操作できるプロダクト 元々はCyberAgent社で開発していた端末管理のOSS 現在はOpenSTFからDeviceFarmerというプロジェクトに名称変更 Web上から端末の操作(APKインストールやWebブラウザ操作、 エクスプローラー等)が可能 →

Slide 17

Slide 17 text

DeviceFarmerについて 17

Slide 18

Slide 18 text

DeviceFarmer 端末リスト 18

Slide 19

Slide 19 text

DeviceFarmer 端末画面 19

Slide 20

Slide 20 text

余談:CyberAgentでは 沖縄に設置されており、ネットワーク越しに 各子会社が利用できるようになっています 20

Slide 21

Slide 21 text

じゃあ、それらを組み合わせると? ステイホームしながら、指定の端末でテストができる 21

Slide 22

Slide 22 text

導入方法から、テスト作成まで 22

Slide 23

Slide 23 text

導入方法 Airtest IDEのインストール https://airtest.netease.com/ 23

Slide 24

Slide 24 text

IDE画面 24

Slide 25

Slide 25 text

導入方法 Unity側にPocoSDKを導入 https://github.com/AirtestProject/Poco-SDK 1.ライブラリのダウンロード 2.使用しているUIに合わせてファイルを削除 3.Unityのプロジェクトに導入 4.PocoManagerをScene上に設置する 25

Slide 26

Slide 26 text

PocoSDK プロジェクトが利用するGUIシステム にあわせて、ファイルの除去を行う 26

Slide 27

Slide 27 text

PocoSDK プロジェクトがuGUIを採用していたら NGUI,fairyguiを削除してUnityへインポート 27

Slide 28

Slide 28 text

PocoManager 導入 #if ENABLE_AIRTEST // Airtestデバッグの為に実体化 var pocoGameObject = new GameObject(); pocoGameObject.name = "Poco"; pocoGameObject.gameObject.AddComponent(); #endif シーン上に予めPocoManagerを 配置しても動作するが、 シンボルで切り分けた方が 取り回しが良い 28

Slide 29

Slide 29 text

Device Farmer の導入 node.js環境か、docker-component環境で構 成してる情報の方が多く、手間も少ないのでおす すめ 時間の都合上割愛しますがDocker環境を整え て、docker-composeファイルを用意し $ docker-compose up 資料末の参考資料に参考にさせ て頂いて、実際に起動させた docker-composeの参照先を記 載しております 29

Slide 30

Slide 30 text

起動画面 30 いきなりログイン画面を要求されますが適当でOK セキュリティを担保したい場合の処理は後述

Slide 31

Slide 31 text

準備中から進まない? ・ログを確認しよう ・起動させる前にUSB接続済み? ・https://github.com/openstf/stf/issues/407 ・https://github.com/openstf/stf/issues/670 導入時インストールされるstf.apk周りの動作チェック    stfアプリをadbで起動させる等の対処法あり 31

Slide 32

Slide 32 text

ワークフロー 開発者はPocoSDK をUnityアプリに組み込む 32 Pocoが組み込まれた APKを出力

Slide 33

Slide 33 text

ワークフロー テスト製作者はDeviceFarmer にアクセスし、端末を確保 33 APKをインストール 端末一覧から端末をクリックす ると「使用状態」になり 他の人が使えないように

Slide 34

Slide 34 text

ワークフロー AirtestIDEを利用して UI情報を取得 34 adb connect した端末は自分 の手元にある端末と同様に あつかえる 誰でも実行可能なように Gitリポジトリに格納。

Slide 35

Slide 35 text

ワークフロー 35 作成したテストはPythonコード として、Jenkins等の実行環境 へ Jenkins側はテスト実行時に DeviceFarmerから端末を確保 し、テストを実行する 新規バイナリか、テストコードの 更新がある度に実行する 結果をSlack等に通知

Slide 36

Slide 36 text

テストコードを書く from airtest.core.api import start_app from poco.drivers.unity3d import UnityPoco # ゲームを起動し、Pythonコードを実行すると # ゲーム内PocoSDKとPythonが接続される。 poco = UnityPoco() # 特定のゲームオブジェクトのタップ poco("BattleButton").click # 長押し処理 poco.long_click(pos=[0, 0], duration=3.0) # テキスト情報の取得 text = poco("ErrorCode").get_text() 36

Slide 37

Slide 37 text

取得できる情報 # UIの名前の取得 poco("CoalitionName").get_name() # UIの座標取得 poco("CoalitionName").get_position() # テキスト値の取得 poco("CoalitionName").get_text() # 体力を確認して、その値が0以下じゃなければ # みたいな処理をよく書いたりする hp = poco("HitPoint").get_text() if hp not 0: 37

Slide 38

Slide 38 text

38 エラーがあったら Slackに通知 def exists_end_report(self, poco): if poco("ErrorCode").exists(): image = poco.snapshot() text = poco("ErrorCode").get_text() self.messenger.upload("screen." + image[1], text, base64.b64decode(image[0])) sys.exit() 画面上にエラーコードが発行さ れていたらslackに投稿する

Slide 39

Slide 39 text

39 指定のスキルが見つ かるまで遷移   def skill_table_pos_check(self, skill_name): pos = self.poco(text=skill_name).get_position() # 画面外に押したいボタンがある while pos[0] < 0 or pos[0] > 1: # スワイプさせたり、ボタンを押したり等の処理 if pos[0] < 0: self.poco("LeftArrowButtonSprite").click() if pos[0] > 1: self.poco("RightArrowButtonSprite").click() pos = self.poco(text=skill_name).get_position()

Slide 40

Slide 40 text

40 動画撮影 poco.device.start_recording() # test.mp4で動画ファイルを出力 poco.device.stop_recording(output="test.mp4") # 中断させる場合はis_interrupted=True poco.device.stop_recording(is_interrupted=True)

Slide 41

Slide 41 text

「自動化」に向けてもうひと工夫 41

Slide 42

Slide 42 text

Python環境側 ・Airtest内で完結するなら .air ・Pythonコードとして動作させるなら .py Pythonの各種ライブラリの取り回しを よくしたいのであればpure pythonで 構築するのがおすすめ 42

Slide 43

Slide 43 text

DeviceFarmerとAirtestの連携 端末画面から、リモートデバッグコマンドをコピペして利用する。 これも自動化したい。 43

Slide 44

Slide 44 text

Device Farmer 端末の確保 Device FarmerはOpenAPI対応なので好みの言語でClientを生成する ・https://github.com/swagger-api/swagger-codegen もしくはJenkinsのプラグインを利用する ・https://plugins.jenkins.io/open-stf 44

Slide 45

Slide 45 text

端末確保の自動化 def main(adb_path, serials): api_instance = create_api_instance() devices = api_instance.get_user_devices() print(devices) for serial in serials: print(serial) device = swagger_client.AddUserDevicePayload(serial) add_user_device(api_instance, device) thread = api_instance.remote_connect_user_device_by_serial(serial, async_req=True) res = thread.get() remote_connect_url = res.remote_connect_url cmd = adb_path + " connect " + remote_connect_url while True: proc = subprocess.run(cmd, shell=True, stdout=PIPE, stderr=PIPE, text=True) time.sleep(1) if 'connected' in proc.stdout: break swagger-codegenを利用し て、Pythonでクライアントを作 成 45

Slide 46

Slide 46 text

ツール利用と組み合わせのまとめ Pocoを組み込み、Airtestでテストを作成、DeviceFarmer環境でテストを行う ・結果はSlackやスプレッドシートに送信  あまりUnitTestのような感覚はなくE2Eで正しく動くか?が大きい ・recording機能で動画を保存できるようにしておく エビデンスとして 46

Slide 47

Slide 47 text

UI名を利用したテストの利点 デザインが変わってもPocoは「PlayButton」 で位置情報を取得できる PlayButton 47 Poco(“PlayButton”).click()

Slide 48

Slide 48 text

テストを作成するチームと開発チームを分離できる テストを作る側は開発チームのコードとは独立したテストコードを作成できる  チームの分離が可能 48 C#知らなくても テストが作れる テスト製作者に 配慮せず設計変更

Slide 49

Slide 49 text

使用事例 49

Slide 50

Slide 50 text

要件 戦国炎舞はGVGのゲーム トップ層はシビアな戦いを行っている バージョンの差異等でレスポンスの悪化があると 非常によろしくない とはいえ、毎回人間がレスポンスを確認するのは… ということで 50

Slide 51

Slide 51 text

Airtestを利用して、高速連打し続ける 30分間攻撃し続けて、バージョン毎の攻撃数に差異がないか? 51

Slide 52

Slide 52 text

CSVで行動を作れるようにする。   特定ルールでのスキル効果チェック 52

Slide 53

Slide 53 text

CSVを利用したテストの作成 53 デバッグ用APIで各種データ調整 対戦相手の設定、ルール等 ログをスプレットシートに記述 端末を操作して自動実行させる API_XXX.py API_XXX.py

Slide 54

Slide 54 text

自動化のタスクを CSVで表現する task_classes = [TaskHttpGet, AttacklTask, TacticsTask, HealTask, SpecialTask, CheerTask, TaskBasicTap, TaskScreenShot, TaskHttpRuleChange, TaskHttpBattleBegin, TaskHttpBattleEnd, TaskHttpEditStatus, TaskStartWar, TaskGameStart, SpreadSheetLogger, TaskHttpEditHp, TaskTriggerCheck] obj_graph = pinject.new_object_graph(binding_specs=[PocoCSVBindingSpec()]) for task in task_classes: instance = obj_graph.provide(task) self.worker[instance.tag()] = instance for index, row in df.iterrows(): if row[0] in self.worker.keys(): var = self.worker[row[0]].action(row) 大まかに表現するとこのような 感じ タスク毎にクラスを作成し、 CSVのコード毎に呼び出す 54

Slide 55

Slide 55 text

CSVを利用したテストの作成 例えば: ・テスト環境を構築するAPI ・「合戦」中に掛かる、倍率のリセット ・実際に端末を操作してテスト内容を実行するコマンド 端末操作とAPI操作を1つのファイルから命令できるので 手順ミス等がなくなる 55

Slide 56

Slide 56 text

Tips おまけ等 56

Slide 57

Slide 57 text

DeviceFarmerのユーザー認証 CyberAgentでは「同一ネットワークのみ&LDAP認証」で運用 https://github.com/openstf/stf/issues/47 LDAP認証ってどうやるの? https://blog.cybozu.io/entry/2018/12/20/110000 サイボウズさんの事例 57

Slide 58

Slide 58 text

高速化のちょっと したコツ poco("UI名").click() が微妙に遅い… 内部の「touch_method」 によって手法が変わる #Before poco = UnityPoco() poco("LeftBgSprite").click() 58

Slide 59

Slide 59 text

高速化のちょっと したコツ dev = device() poco = UnityPoco() screen_width, screen_height = poco.get_screen_size() pos_attack_scale_x, pos_attack_scale_y = poco("LeftBgSprite").get_position() pos_x = screen_width * pos_attack_scale_x dev.minitouch.touch((pos_x, pos_y)) https://github.com/DeviceFarmer/minitouch 59

Slide 60

Slide 60 text

起動時にUSBで接続済みのデバイスに モジュールがインストールされる 接続しているAndroid端末に必要なモジュールがインストールされる  minicap デバイスキャプチャツール ・https://github.com/openstf/minicap   ・スクリーンショットの高速なやり取りに利用する  minitouch android内のinputファイルを書き換えるツール ・https://github.com/DeviceFarmer/minitouch   ・高速にタッチする処理等に利用 60

Slide 61

Slide 61 text

minitouch,minicapは元々OpenSTFの プロジェクト 個別に公開されていたものが、Airtestで利用されているOSSとして公開したも のが別のプロジェクトで利用されOSSを公開した会社でそのプロジェクトを利用 する。という面白い構図。 61

Slide 62

Slide 62 text

DeviceFarmerのiOS周り issueは上がっていて、プルリクエスト用のプロジェクトも進んでいる。 自分でXcode周りのビルドができるのであれば試すことはできそう。 間に合えば資料アップロード時にここらへんの資料を追加します。 62

Slide 63

Slide 63 text

AirtestとiOS :ちょっとまだ非推奨 (スピードが遅い…) https://airtest.doc.io.netease.com/en/tutorial/6_IOS_automated_t esting/ を参考に https://github.com/AirtestProject/iOS-Tagent ↑をXcodeでビルドして、端末にインストール Mac上でhomebrewを導入し、brew install usbmuxd iproxy 8100 8100で接続 63

Slide 64

Slide 64 text

Pocoを拡張する Pocoは、GameObject内の Componentを取得して内部の 値を返すという動きをしている ライブラリを拡張すれば独自の Componentの特定の値を 取ってこれる 64

Slide 65

Slide 65 text

ADBを「合わせる」 ADBのバージョンをあわせないと、AirtestやCLIで実行する際にADBを kill-server start-serverを繰り返すことになるので対応したい PIPとAirtestの中のadbをあわせるのにリンクを作成しておくとよい 65

Slide 66

Slide 66 text

DeviceFarmerを自力で用意するのが大変 https://www.headspin.io/ headspinさんのような サービスを利用するのも 一つの手段 66

Slide 67

Slide 67 text

まとめ 1.実機による自動テストが可能になることで、安定稼働とチームの安心感向上 に寄与することができる 2.プロジェクト外からテストによる貢献ができるので開発リソースの柔軟な投入 が可能プロジェクト側にも負担をかけない 3.Pythonの知識が多少要求されるが、十分習得可能な範囲と考えられ、非プ ログラマーでも自動のテストが構築できる 67

Slide 68

Slide 68 text

まとめ アイディアと今後の開発でさらに有効活用できると考えておりますので、みなさ んと一緒にいろいろ考えていけたら良いなと思っております。 68

Slide 69

Slide 69 text

参考文献や素材等 かわいいフリー素材集 いらすとや 4,750,000+ free and premium vector icons in SVG, PNG, CSH and AI format. Azusa 3 - 大体いい感じになる無料 Keynote・Googleスライドテンプレート 【Unity】「Airtest IDE」を使用して Android のゲームで画像認識による UI の自動テストを試してみた Androidのリモート操作/管理ツール「OpenSTF」をDocker for Windowsで使う OpenSTF+Dockerで社内Android端末管理システムを Mac上に構築する https://airtest.netease.com/ AirtestProject/Poco-SDK Device Farmer stfのiosサポート https://github.com/tmobile/stf_ios_support Welcome to Poco (ポコ) documentation! — poco 1.0 documentation 69