yotiky Tech Blog

とあるエンジニアの備忘録

Unity Unit Test(単体テスト)入門 - Unity Test Framework

目次

はじめに

  • この一連の記事は
    • UnityのUnity Test Frameworkを使ったテストに関して調べたメモ書きに補足を足したもの
    • Unityのテスト、およびDIコンテナ、モックライブラリの基本的な使い方やそれぞれの役割など入門レベルの解説
    • ライブラリのリファレンス的な使い方などについては公式や他の記事参照
    • 実機テストやCIは含まない
    • TDDに関しては考慮しない

シリーズの目次

環境

Unity Test Framework

手順

  • Test Framework 入ってなければ追加する
    • 1.3から非同期使えるのでバージョンを更新する
    • Package Managerから
      • by url : com.unity.test-framework@1.3
      • by name : com.unity.test-framework/1.3.9
  • Test Runner ウィンドウを開く
  • テストのアセンブリを定義する
    • PlayMode、EditModeそれぞれAssebly Folderを作成
  • アプリのアセンブリを定義する
    • アセンブリ定義を作成する
    • テストのアセンブリ定義にアプリのアセンブリ定義の参照を追加する
    • Assembly-CSharp.dllを直接参照しない
      • Workflow: How to create a Play Mode test | Test Framework | 1.3.9
      • Enable playmode tests for all assembliesはエディタから直接触れなくなっている
        • 一応、ProjectSettings.asset を直接開いて、playModeTestRunnerEnabledを1にすれば使える
        • ビルドする前に0に戻す必要がある
        • Test Runnerのタブを右クリックすると、無効化するために再起動を求められる、再起動後0に戻ってる
  • テストコードを実装する
  • Test Runner ウィンドウからテストを実行する

参考

補足

  • テストモード
    • EditMode
      • エディタ上で実行される
      • EditModeのテストからPlayModeの開始と終了を呼ぶこともできる(EnterPlayMode/ExitPlayMode
        • 専用のSceneを作成して再生するが、元のテストはエディタ上で実行されてるのでWaitForSecondsは使えないまま
    • PlayMode
      • テスト専用のSceneが作成され、エディタのPlay(再生)で実行される
      • ターゲットプラットフォーム上でもテストできる
      • ただし、UnityTest属性はWSAをサポートしていない
    • Edit Mode vs. Play Mode tests | Test Framework | 1.3.9
  • テストタイプ

    • Test属性
      • フレームをまたがない通常のNUnitテスト
      [Test]
      public void Test属性のTest()
      {
          Assert.That(1 < 10);
      }
    
    • UnityTest属性
      • EditMode
        • エディタのアップデートループ EditorApplication.update でテストを実行する
        • yield return null でフレームを進める
      • PlayMode
        • Sceneの中でコルーチンとしてテストを実行する
        • yield returnは通常のコルーチンと同様WaitForSecondsが使える
      [UnityTest]
      public IEnumerator UnityTest属性のTest()
      {
          Assert.That(1, Is.LessThan(10));
          yield return null;
          Assert.That(2, Is.LessThan(10));
          yield return null;
          Assert.That(3, Is.LessThan(10));
      }
    
  • 非同期テスト

    • バージョン1.3以降
      • EditMode/PlayMode両方で使える
      • Test属性のテストメソッドでasync Taskが使える
      • メソッド内ではTask、UniTaskが使え、DelayやDelayFrameなどフレームをまたぐ処理も可能
        [Test]
        public async Task 非同期TaskのTest()
        {
            await Task.Delay(2000);
            Assert.That(true);
        }
        [Test]
        public async Task 非同期UniTaskのTest()
        {
            await UniTask.Delay(2000);
            await UniTask.DelayFrame(1000);
            Assert.That(true);
        }
      
    • バージョン1.3より前
      • UnityTest属性で、UniTask.ToCoroutinが使える
        [UnityTest]
        public IEnumerator 古いUniTaskコルーチンを使ったTest() 
            => UniTask.ToCoroutine(async () =>
            {
                await UniTask.Delay(2000);
                await UniTask.DelayFrame(1000);
                Assert.That(true);
            });
      
  • Assert

  • テストの前後処理

          [OneTimeSetUp]
          public void OneTimeSetUp() => Debug.Log("OneTimeSetUp");
    
          [OneTimeTearDown]
          public void OneTimeTearDown() => Debug.Log("OneTimeTearDown");
    
          [SetUp]
          public void Setup() => Debug.Log("Setup");
    
          [TearDown]
          public void TearDown() => Debug.Log("TearDown");
    
          [UnitySetUp]
          public IEnumerator UnitySetUp()
          {
              Debug.Log("UnitySetUp");
              yield return null;
          }
    
          [UnityTearDown]
          public IEnumerator UnityTearDown()
          {
              Debug.Log("UnityTearDown");
              yield return null;
          }
    
          [Test]
          public void TestCase1() => Debug.Log("TestCase1-Test");
    
          [UnityTest]
          public IEnumerator TestCase2()
          {
              Debug.Log("TestCase2-UnityTest");
              yield return null;
          }
    
  • Sceneをロードする
    • PlayModeでのみ可能
    • 対象のSceneをBuild Settingsでビルドの対象に追加して、SceneManager.LoadScene("SceneName")
      [UnityTest]
      public IEnumerator SceneをロードするTest()
      {
          var name = "SceneLoadTest";
    
          LogAssert.Expect(LogType.Log, $"Hello from {name}");
    
          SceneManager.LoadScene(name);
    
          yield return null;
      }
    

MEMO

参考