ARアプリ開発におけるCI/CD

Hiroyuki Makino
nttlabs
Published in
16 min readSep 24, 2020

前回の記事では、ARアプリのテストやデバッグは大変だという話題をとりあげました。 今回は、ARアプリ開発でCI/CDを回せるようにすることを目標に、どのようにすればARアプリのテストを省力化できるのか深堀りしていきたいと思います。 また、PoCとして開発環境やGithub Actionsを使ったCI環境でARの挙動をテストする仕組みを作りましたのでご紹介したいと思います。

目次

  1. CI/CDとは?
  2. ARアプリの開発手法
  3. ARアプリのテスト
  4. ARアプリのテスト自動化の検討
  5. ARアプリのテスト自動化における課題
  6. ARアプリのテスト自動化に向けたアプローチ
  7. まとめ

1. CI/CDとは?

CI/CDとは、継続的インテグレーション(Continuous Integration)/継続的デリバリー(Continuous Delivery)の略で、ソフトウェア開発においてテスト、ビルド、デプロイを自動的かつ継続的に行えるようにするアプローチを指します。小さなサイクルで繰り返しこのアプローチを実施することでソフトウェア品質の向上と開発効率の向上に繋がり、短期間でのソフトウェアのリリースや改善が期待できます。

ARアプリ開発のコンテクストと照らし合わせてみると、前回の記事で言及したように、開発の現場においては、端末にビルドして実機で確認したり、手作業で確認したりといった人手の介在や、変化する環境下に対してテストのバリエーションを増やさなければならないといったことがテストを行う上でのボトルネックになっていましたので、これらをプログラマブルにできるようにすることがCI/CDにつながると考えられます。

2. ARアプリの開発手法

いくつかARアプリの具体例をもとに、ARアプリをどのように開発するか説明し、必要となるテストシナリオを挙げてみましょう。

1. オンラインショッピングでの3Dモデルを使った商品の確認や家具の配置など、ユーザが指定した場所にARを出現させるアプリ

ユーザのタップなどのアクションによって認識した平面にレイキャストを行い、取得できた座標にオブジェクトを配置します。 ここで必要なテストは、様々な環境下で適切に平面が認識できること、ユーザのアクションによって3Dモデル(オブジェクト)が適切な向きや大きさで配置できることといったことになるでしょう。

2. バーチャル広告や機器のマニュアルなど、場所紐付けて固定的にARを出すアプリ

特定の画像に紐付けるためのイメージアンカーを利用したり、場所に固定的に紐付ける場合は、Google Cloud AnchorsAzure Spatial AnchorsなどのARクラウドのアンカーを利用して、配置したオブジェクトとデバイスの位置関係を復元(リローカライズ)できるようにします。 ここで必要なテストは、3Dモデル(オブジェクト)が適切な向きや大きさで配置できるといったことに加え、光量など変化する環境下で空間の特徴量が適切に取得できアンカーを復元できるかといった、位置に関するテストも必要になるでしょう。

3. 対戦ゲームや建築シミュレーションなど、複数人で同じAR空間を共有するアプリ

アンカーの利用に加え複数クライアント間でオブジェクトの変更を同期させるために、Photonなどのリアルタイムネットワークエンジンを利用します。 ここで必要なテストは、2で挙げたテストに加え、複数端末間で一方のアクションが他方に正常に伝搬するかといったテストや、同時性の面では同期の遅延もテストする必要がありそうです。

3. ARアプリのテスト

前述したテストをまとめると以下のようなテストがARのコンテクストでは必要になると言えるでしょう。

[イベントの発生] タップによって指定したオブジェクトを出現させる — 正常にオブジェクトが配置されるか

[オブジェクトの向き、大きさ] 配置オブジェクトのサイズや向きを調整する — 配置されたオブジェクトの大きさや向きが適切か

[アンカーの位置] 空間情報からアンカーを検索し、アンカーに紐づくオブジェクトを復元させる — アンカーが正しい位置で検索でき、復元されるオブジェクトが正しい位置に配置されるか

[オブジェクトへのインタラクション] オブジェクトに対するアクションが動作する — オブジェクトの移動、オブジェクト間でのコリジョンなどが正しく発生するか

[オブジェクトの同期] マルチプレーヤー間でオブジェクトが同期される — 正常に伝搬するか、遅延なく同期されるか

[オブジェクトの見た目] オブジェクトが現実空間に調和する — 光源やオクルージョン、位置が適切でオブジェクトが自然に見えるか

4. ARアプリのテスト自動化の検討

では、ARアプリのテストで挙げたテスト内容をプログラマブルにする方法を考えていきたいと思います。 ARアプリ開発では、開発環境としてUnityを利用している開発者が多いと思いますので、ここでは、Unityで開発していることを想定し、Unityの標準テストフレームワークであるUnity Test Framework(以前はUnity Test Runnerと呼ばれていました)を用いた例を示します。

[イベントの発生]

タップによるオブジェクト配置は、Raycastを取得した後にInstantiate()メソッドでオブジェクトのprefabをインスタンス化する処理を記述することが多いと思いますので、テストでは、このインスタンスが生成されているかどうかをAssertでチェックします。 例えば、オブジェクトにTagを付けておいて、FindGameObjectsWithTag()メソッドでオブジェクトを探し、インスタンス化されたオブジェクトが0でないことをAssert.AreNotEqual()メソッドで確認します。

obj = GameObject.FindGameObjectsWithTag("arobject");
UnityEngine.Assertions.Assert.AreNotEqual(obj.Length, 0);

[オブジェクトの向き、大きさ]

オブジェクトの向きや大きさはtransform.rotationやtransform.localScaleで取得できそうです。 テストでは以下のようにAssert.AreApproximatelyEqual()メソッドで想定した範囲内であることをチェックできそうです。

obj = GameObject.FindGameObjectsWithTag("ar1");
var quaternion = obj[0].transform.rotation;
Quaternion expected = new Quaternion(0.0f, 1.0f, 0.0f, 0.1f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(expected.x, quaternion.x, 0.1f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(expected.y, quaternion.y, 0.1f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(expected.z, quaternion.z, 0.1f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(expected.w, quaternion.w, 0.1f);
var size = obj[0].transform.localScale;
UnityEngine.Assertions.Assert.AreApproximatelyEqual(1.2f, size.x, 0.2f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(1.2f, size.y, 0.2f);
UnityEngine.Assertions.Assert.AreApproximatelyEqual(1.2f, size.z, 0.2f);

[アンカーの位置]

アンカーが正しい位置で検索できたかどうかをチェックするには、実際にリローカライズしてアンカーを取得する必要があるため、テスト時にはカメラ画像などの空間の情報を入力する必要がありそうです。 この点がARのテストで人手を介したり、ビルドして実機で確認したりといった手順を生んでいると考えられます。ARアプリのテスト自動化における課題で後述します。 入力を元にして、アンカーが取得できれば、空間におけるアンカーとデバイスが居る位置(一般的にARではアプリケーションが開始された地点を起点とします)を変換し、マッピングできるようになります。あとは、前述したようにAssertを使って配置したオブジェクトの位置や向きをテストするとよさそうです。

[オブジェクトへのインタラクション]

オブジェクトにRigidbodyやColliderを使って物理シミュレーションを行い、物体の落下や回転、衝突といった動きをつけるといった処理を記述することを想定します。 例えば、ARで認識した平面に物体を落下させるといった動作では、平面にMeshColliderをアタッチし、オブジェクトが衝突したときに呼ばれるOnCollisionEnterを使って、平面に衝突したかどうかをAssertでチェックすれば良さそうです。 このテストでも、空間を認識して平面が生成されていることが前提になるので、テスト時にはカメラ画像をもとにした空間の情報を入力する必要がありそうです。

void OnCollisionEnter(Collision collision) {
UnityEngine.Assertions.Assert.IsTrue(collision.gameObject.tag == planeTag);
}

[オブジェクトの同期]

複数クライアント間でネットワーク越しにオブジェクトを同期させる場合、UnityではPUN(Photon Unity Networking)やMUN(Monobit Unity Networking)がよく利用されているようです。 Photonの例であれば、同期させたいオブジェクトにPhotonViewコンポーネントをアタッチし、PhotonView.RPC()メソッドをコールすると位置、回転、プロパティ値をネットワーク越しに同期できます。 複数クライアント間で連携させたい場合、テスト用のRPCメソッドを用意して、PhotonView.RPC()メソッドで同期させ、オブジェクトの位置などをAssertでテストするとよさそうです。

[オブジェクトの見た目]

オブジェクトの向きや大きさ、位置といった幾何学的整合性は定量的なテストが可能ですが、オブジェクトが現実空間に調和するかといった質感に関する光学的整合性は定性的であり、現実空間の光源環境などにも影響されるため、現状、プログラマブルに行うのが困難な項目と考えられます。 しかし、最近ではレンダリングされた画像から「物体形状」「反射特性」「光源分布」を推定するインバースレンダリングといった手法も盛んに研究されています。この手法を応用し、計算された光源が実際の光源に近いかどうか判定することでARの影や色調が適切か検知することが可能になるかもしれません。

5. ARアプリのテスト自動化における課題

ARアプリのテストを自動化する上での課題は、入力データへの対応、光学的整合性への対応、マルチデバイスへの対応が挙げられます。

1つ目の入力データへの対応については、AR体験がデバイスのカメラやセンサによる姿勢情報の入力に基づいていることに起因します。これについては、例えば入力を予め記録しておき、テスト時にデータをリプレイ再生したり、3Dモデルを作成し、3Dモデル内をウォークスルーすることで入力を擬似的に生成するといった対応が考えられます。

2つ目の光学的整合性への対応については、ARの見た目が環境光など周囲の環境に依存することに起因することが挙げられます。様々な環境下における入力データを用意しておき、レンダリング結果をスコアリングしてチェックするといった対応が考えられます。

3つ目のマルチデバイスへの対応については、デバイスごとに空間の認識性能や視野角といった特性が異なることに起因すると考えられます。各デバイスで取得した入力データに加え、デバイスの挙動を再現できるエミュレータが必要になってくるでしょう。

6. ARアプリのテスト自動化に向けたアプローチ

ARアプリのテスト自動化に向けたアプローチの一つとして、ARの入力データ(カメラ画像や認識した平面、レイキャスト、ポーズ情報等)を記録しておき、テスト時にデータをUnity上で再生して、Unity Test Framework上でARの挙動をテストできる概念実証(PoC)を作成しました。

ARデータのリプレイにより、実機ビルドを行うことなく、実機から収集したデータを利用して、エディタ上でARを動作させることが可能になります。Unity Test Frameworkのような標準的なテストフレームワークをARのテストに利用し、自動化することでテスト工数削減につながります。
例えば頻繁にコンテンツをアップデートするARアプリのレグレッションテストや取り扱うオブジェクトが多数あるようなARアプリでのテストに効果的であると考えられます。さらに、ARの入力データを複数パターン用意しておき、ARの実行環境の変化に対するテストにも利用できると考えられます。

以下のデモ動画はタップによるオブジェクト配置イベントが正常に発生することをAssertで確認する例になります。ARオブジェクトが想定通りに出現していない場合、右側のウィンドウの例のようにテスト結果NGとして検出できるようになっています。

Unity Test Runner上でARの挙動をテストするデモ

ARデータの保存

AR Foundationで取得できるARデータには、Device tracking、Plane tracking、Point clouds、Face tracking、Meshing、RaycastなどARKitであればほとんどのデータが取得できます。今回ARデータ保存形式は、ARKitのリモートデバッガーとしてKoki Ibukuroさんが公開されているARKitStreamerを参考に端末とPCを接続して転送しているパケットデータとカメラ画像を端末単体で保存できるように実装しました。以下にサンプルコードを示します。

ARデータの再生

ARデータの再生は、保存したパケットデータとカメラ画像データをエディタ上で読み込み、ARKitStreamerのReceiverに渡す実装としました。サンプルコードを以下に示します。Receiverでは、AR FoundationにARデータを送信するカスタムなAR Subsytemsがロードされエディタ上でARが再現できるようになっています。

ARのテスト

4章で述べたARの挙動をテストするコードの例を以下に示します。以下のサンプルコードでは、ARオブジェクトが正常にインスタンス化されているかといったイベントの発生、ARオブジェクトのサイズや向きが適切かといったテストをUnitTestとして記述しています。

CIの自動実行

さらにPoCでは、CIとしてGithub Actionsを利用して、レポジトリへのコードのpushをトリガーにUnityのPlayModeテストを走らせ、ARの挙動をテストできることを確認しています。ワークフロー定義の例を以下に示します。

name: Test projecton:
pull_request: {}
push: { branches: [master] }
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
jobs:
testAllModes:
name: Test in ${{ matrix.testMode }} on version ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- ./
unityVersion:
- 2019.3.2f1
testMode:
- playmode
- editmode
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/cache@v1.1.0
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}
restore-keys: |
Library-
- uses: webbertakken/unity-test-runner@v1.4
id: tests
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts
- uses: actions/upload-artifact@v1
with:
name: Test results for ${{ matrix.testMode }}
path: ${{ steps.tests.outputs.artifactsPath }}

7. まとめ

AR開発の現場においては、端末にビルドして実機で確認したり、手作業で確認したりといった人手の介在や、変化する環境下に対してテストのバリエーションを増やさなければならないといったことがテストを行う上でのボトルネックになります。これらをプログラマブルにし、自動化することが、AR開発の開発コスト削減につながると考えられます。

本記事では、ARのテストにおけるテストパターンや自動化に向けたアプローチを検討し、アプローチの一つとして、ARデータの記録、再生によるテスト自動化のPoCを行いました。

今後の取り組みとして、ARクラウドを利用するようなより大規模なARのテストに対応できるようにすることや、深層学習推論を組み合わせてARの見た目をテストするといったシナリオの高度化に向けた検討が必要であると考えられます。 NTTでは、その手の仕組みを創る仕事に興味のある仲間を募集中です。ご連絡お待ちしています。

--

--

Hiroyuki Makino
nttlabs
Writer for

XR Metaverse Researcher, R&D Engineer at NTT, Japan. Excited for the future of AR and what amazing people create.