やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Unity Automated QAのInput Systemサポートによる自動テスト

Unity Automated QAパッケージのRecorded Playback機能は、デフォルトではuGUI操作を記録・再生します。 しかし限定的ですが「Input Systemサポート」も提供されており、以下の操作に限り動作させることができ(ると書かれてい)ます。

  • UnityEngine.Input(従来のInput Manager)のみ*1
    • Supported Attributes: touches, touchCount, mousePosition
    • Supported Methods: GetTouch, GetMouseButton, GetMouseButtonDown, GetMouseButtonUp, GetKey, GetKeyDown, GetKeyUp, GetButton, GetButtonDown, GetButtonUp

Input Systemサポートについて、昨年末の同人誌『Unity Automated QA攻略ガイド』で調査途中と書いたままとなっていましたが、改めて調査してみました。 今さら感ありますが、そろそろホールドされているAutomated QAパッケージの開発が再開されるとされている時期なので期待も込めて。

www.nowsprinting.com

テスト対象の準備

Unity Asset Storeで無償提供されている2D Game Kit v1.9.5を使用しました。 選定理由は、New Input SystemおよびInput.GetAxis()*2を使っていないためです。

assetstore.unity.com

Unity 2022.1.20f1で開いたところ、UnityEngine.RuleTileがUnity.2D.Tilemap.Extras内にも定義されているというエラーが出たため、Assets/2DGamekit/Scripts/Utility/RuleTile.cs内のものをRuleTile2にリネームしています。

ここに、Automated QAパッケージをインストールします。 一覧には出てきませんが、 Package ManagerのAdd package by name...で"com.unity.automated-testing"を入力すればインストールできます。

記録のための設定

デフォルトではInput Managerによるキー入力は記録されません。 UnityエディタのメニューからAutomated QA | Automated QA Hub | Settingsを開き、Record Input Managerをonにします*3

再生のためのコード修正

続いて、キャラクター操作部分を少し書き換えます。 2D Game Kitでは、Inputから直接入力を取得しています。これにAutomated QAのPlaybackが介入できるよう、RecordableInputに置き換えます。

ファイルは、Assets/2DGamekit/Prefabs/EllenにアタッチされているAssets/2DGamekit/Scripts/Character/MonoBehaviours/InputComponent.csです。

次のような箇所を

Down = Input.GetButtonDown(k_ButtonsToName[(int)controllerButton]);

このように書き換えます*4

Down = RecordableInput.GetButtonDown(k_ButtonsToName[(int)controllerButton]);

Automated QAのアセンブリへの参照が必要です。 製品では、リリースビルドから除くため #if (UNITY_EDITOR || UNITY_INCLUDE_TESTS) を使うなどしたほうがいいでしょう*5

Automated QAパッケージにパッチを当てる

Input Managerの記録部分にバグがあり、パッチを当てる必要があります。 これは操作を記録する工程で必要なパッチであり、記録されたJSONファイルの再生時には無くても問題ありません。 言い換えると、再生だけならパッチを当てない素のパッケージを利用できます。

まず、パッチを当てるために、Automated QAパッケージを組み込みパッケージ化します。 プロジェクトディレクトリ下のLibrary/PackageCache/com.unity.automated-testing@0.8.1-preview.2を、Packagesディレクトリ下にコピーするだけです。

続いて、Packages/com.unity.automated-testing@0.8.1-preview.2/Runtime/RecordedPlayback/RecordingInputModule.csを開き、次の箇所を変更します。

internal void AddFullTouchData(TouchData td, bool setLastEventTime = false)
{
    playbackData.Add(td);  // ここを recordingData.Add(td); に書き換える

    if (setLastEventTime)
    {
        lastEventTime += td.timeDelta;
    }
}

Recorded Playback

以上の設定・修正を行った状態で、Automated QA | Automated QA Hub | Recorded Playbackを開き、Recordボタンで記録を開始します。 記録終了後に生成されるJSONファイルには、次のようにキー入力も記録されています。

Dキーを押して離した箇所の抜粋)

"touchData": [
{
    "pointerId": 0,
    "eventType": 5,
    "timeDelta": 1.9524928331375123,
    "position": {
        "x": 0.0,
        "y": 0.0
    },
    "positional": false,
    "scene": "Zone1",
    "button": 0,
    "waitSignal": "",
    "emitSignal": "",
    "keyCode": "D",
    "inputText": "",
    "inputDuration": 0.496268630027771,
    "objectName": "",
    "objectTag": "",
    "objectHierarchy": "",
    "objectIndex": 0,
    "querySelector": "",
    "objectOffset": {
        "x": 0.0,
        "y": 0.0
    }
},
{
    "pointerId": 0,
    "eventType": 9,
    "timeDelta": 0.0,
    "position": {
        "x": 0.0,
        "y": 0.0
    },
    "positional": false,
    "scene": "Zone1",
    "button": 0,
    "waitSignal": "",
    "emitSignal": "",
    "keyCode": "d",
    "inputText": "",
    "inputDuration": 0.496268630027771,
    "objectName": "",
    "objectTag": "",
    "objectHierarchy": "",
    "objectIndex": 0,
    "querySelector": "",
    "objectOffset": {
        "x": 0.0,
        "y": 0.0
    }
},

このファイルを指定して再生すると、キー入力による左右移動やジャンプが再現されました!

なお、マウスクリックも記録されますが、"keyCode": "Fire1" の入力として記録され、座標は常に { 0, 0 } となりますので注意してください。

Test Generation

続いてテストコード生成を試します。 3種類の生成方法がありますが*6、"Full Tests"の場合は"Use Simplified Driver Code"をオフにしたほうがよさそうです。

"Full Tests"かつ"Use Simplified Driver Code"がオンの場合、再生がスムーズでなくなります(はじめのほうのフレームが無視されている?)。

"Use Simplified Driver Code"がオフ、もしくは"Simple Tests"であれば、スムーズに再生されました。

所感

PCやコンソール向けの場合、素直にNew Input Systemを使うほうが自動化は楽なはずです。 また、Automated QAパッケージの開発が再開されたとして、レガシーなInput Managerのサポートを続けるのかは謎です。 したがって、この記事が役に立つことはない気がしますが、供養のため公開します。

*1:であればInput Systemと呼ばないでほしいところですが、ソースを見るとNew Input Systemもサポートしようとする形跡が見えます

*2:Input Systemサポート対象外です。このため3Dゲームのサンプルにはほぼ適用できません

*3:ドキュメントに書かれていなくて忘れがち

*4:ゲームコントローラ向けに一箇所だけGetAxisRaw()があります。これはサポート外なので、RecordableInputに置き換えても再生されません。なお、未サポートのメソッドはUnityEngine.InputにフォールバックされていますのでInputとしての振る舞いはキープされます

*5:ちゃんとビルドからストリップされるかは要検証

*6:詳しくは『Unity Automated QA攻略ガイド』参照