Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AirtestとPocoとOpenSTFによるUnity製スマートフォン向けゲームの実機自動テスト環境構築とその利用方法

 AirtestとPocoとOpenSTFによるUnity製スマートフォン向けゲームの実機自動テスト環境構築とその利用方法

「CEDEC 2020」の発表資料です。
http://cedec.cesa.or.jp/2020/session/detail/s5e82a55322244

CyberAgent SGE Engineer

September 04, 2020
Tweet

More Decks by CyberAgent SGE Engineer

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. Airtestについて
    11

    View Slide

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

    View Slide

  13. Airtestでできること
    13

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. DeviceFarmerについて
    17

    View Slide

  18. DeviceFarmer 端末リスト
    18

    View Slide

  19. DeviceFarmer 端末画面
    19

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. IDE画面
    24

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  35. ワークフロー
    35
    作成したテストはPythonコード
    として、Jenkins等の実行環境

    Jenkins側はテスト実行時に
    DeviceFarmerから端末を確保
    し、テストを実行する
    新規バイナリか、テストコードの
    更新がある度に実行する
    結果をSlack等に通知

    View Slide

  36. テストコードを書く
    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

    View Slide

  37. 取得できる情報
    # 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

    View Slide

  38. 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に投稿する

    View Slide

  39. 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()

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  45. 端末確保の自動化
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49. 使用事例
    49

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. 自動化のタスクを
    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

    View Slide

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

    View Slide

  56. Tips おまけ等
    56

    View Slide

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

    View Slide

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

    View Slide

  59. 高速化のちょっと
    したコツ
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  63. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  69. 参考文献や素材等
    かわいいフリー素材集 いらすとや
    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

    View Slide