テストの作成と実行 — MRTK2

MRTK の信頼性を確保するために、MRTK にはコードを変更しても既存の動作が後退しないことを確認するための一連のテストが用意されています。 MRTK のような大きなコードベースで適切なテスト範囲を網羅することは、変更時の安定性と信頼性を高めるために非常に重要です。

MRTK では、NUnit の Unity 統合を使用する Unity Test Runner を使用します。 このガイドでは、MRTK にテストを追加する方法の開始点を示します。 ここでは、提供されているリンクで調べることができる Unity Test RunnerNUnit については説明しません。

pull request を送信する前に、次のことを確実に行ってください。

  1. テストをローカルで実行し、変更によって既存の動作が後退しないようにします (何らかのテストが失敗した場合、PR は完了できません)。

  2. バグを修正する場合は、修正をテストするテストを作成し、今後のコード変更で再発しないようにします。

  3. 機能を作成する場合は、今後のコード変更によってこの機能が壊れるのを防ぐために新しいテストを作成します。

現在、再生モード テストは Unity 2018.4 での実行を想定しており、他のバージョンの Unity では失敗するおそれがあります

テストを実行する

Unity エディター

Unity Test Runner は、[Window]>[General]>[Test Runner] にあり、使用可能なすべての MRTK 再生および編集モード テストが表示されます。

コマンド ライン

テストは、Scripts\test\run_playmode_tests.ps1 にある powershell スクリプトでも実行できます。 これにより、github または CI で実行されているのと全く同じように再生モード テストが実行され (下記参照)、結果が出力されます。 スクリプトを実行する方法の例をいくつか次に示します

Unity 2018.4 (Unity 2018.4.26f1 など) を使用して、H:\mrtk.dev にあるプロジェクトに対してテストを実行します

.\run_playmode_tests.ps1 H:\mrtk.dev -unityExePath "C:\Program Files\Unity\Hub\Editor\2018.4.26f1\Editor\Unity.exe"

Unity 2018.4 を使用して、H:\mrtk.dev にあるプロジェクトに対してテストを実行し、結果を C:\playmode_test_out に出力します

.\run_playmode_tests.ps1 H:\mrtk.dev -unityExePath "C:\Program Files\Unity\Hub\Editor\2018.4.26f1\Editor\Unity.exe" -outFolder "C:\playmode_test_out\"

また、run_repeat_tests.ps1 スクリプトを使用して、再生モード テストを複数回実行することもできます。 run_playmode_tests.ps1 で使用されるパラメーターはすべて使用できます。

.\run_repeat_tests.ps1 -Times 5

pull request の検証

MRTK の CI は、すべての構成で MRTK をビルドし、すべての編集および再生モードのテストを実行します。 ユーザーが十分な権限を持っている場合は、github PR /azp run mrtk_pr にコメントを投稿することによって、CI をトリガーできます。 CI の実行は、PR の [Checks] (チェック) タブで確認できます。

すべてのテストに合格した後にのみ、PR を main にマージできます。

ストレス テスト/一括テスト

テストがごくまれに失敗することがあり、そのデバッグにイライラする場合があります。

複数のテストをローカルで実行するには、該当するテスト スクリプトを変更します。 次の Python スクリプトを使用すると、このシナリオがより便利になります。

Python スクリプトを実行するための前提条件は、Python 3.X がインストールされていることです。

1 つのテストを複数回実行する必要がある場合:

[UnityTest]
public IEnumerator MyTest() {...}

コマンド ラインから以下を実行します (PowerShell をお勧めします)

cd scripts\tests
# Repeat the test 5 times. Default is 100
python .\generate_repeat_tests.py -n 5 -t MyTest

出力をコピーしてテスト ファイルに貼り付けます。 次のスクリプトは、複数のテストを順に実行するためのものです。

cd scripts\tests
# Repeat the test 5 times. Default is 100
python .\generate_repeat_tests.py -n 5 -t MyTest MySecondTest

これで、新しいテスト ファイルには次のものが含まれます

[UnityTest]
public IEnumerator A1MyTest0(){ yield return MyTest();}
[UnityTest]
public IEnumerator A2MyTest0(){ yield return MyTest();}
[UnityTest]
public IEnumerator A3MyTest0(){ yield return MyTest();}
[UnityTest]
public IEnumerator A4MyTest0(){ yield return MyTest();}
[UnityTest]
public IEnumerator MyTest() {...}

テスト ランナーを開き、繰り返し呼び出すことができるようになった新しいテストを確認します。

テストを作成する

新しいコードに追加できるテストの種類は 2 つあります

  • 再生モード テスト
  • 編集モード テスト

再生モード テスト

MRTK 再生モード テストには、手や目などのさまざまな入力ソースに対する新しい機能の反応をテストする機能があります。

新しい再生モード テストは BasePlayModeTests を継承するか、以下のスケルトンが使用できます。

新しい再生モード テストを作成するには:

  • [Assets] (アセット)> [MRTK] > [Tests] (テスト) > [PlayModeTests] の順に移動します
  • 右クリックして、[Create] (作成) > [Testing] (テスト) > [C# Test Script] (C# テスト スクリプト)
  • 既定のテンプレートを以下のスケルトンに置き換えます
#if !WINDOWS_UWP
// When the .NET scripting backend is enabled and C# projects are built
// The assembly that this file is part of is still built for the player,
// even though the assembly itself is marked as a test assembly (this is not
// expected because test assemblies should not be included in player builds).
// Because the .NET backend is deprecated in 2018 and removed in 2019 and this
// issue will likely persist for 2018, this issue is worked around by wrapping all
// play mode tests in this check.

using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities;
using NUnit.Framework;
using System;
using System.Collections;
using System.Linq;
using UnityEngine;
using UnityEngine.TestTools;

namespace Microsoft.MixedReality.Toolkit.Tests
{
    class ExamplePlayModeTests
    {
        // This method is called once before we enter play mode and execute any of the tests
        // do any kind of setup here that can't be done in playmode
        public void Setup()
        {
            // eg installing unity packages is only possible in edit mode
            // so if a test requires TextMeshPro we will need to check for the package before entering play mode
            PlayModeTestUtilities.InstallTextMeshProEssentials();
        }

        // Do common setup for each of your tests here - this will be called for each individual test after entering playmode
        // Note that this uses UnitySetUp instead of [SetUp] because the init function needs to await a frame passing
        // to ensure that the MRTK system has had the chance to fully set up before the test runs.
        [UnitySetUp]
        public IEnumerator Init()
        {
            // in most play mode test cases you would want to at least create an MRTK GameObject using the default profile
            TestUtilities.InitializeMixedRealityToolkit(true);
            yield return null;
        }

        // Destroy the scene - this method is called after each test listed below has completed
        // Note that this uses UnityTearDown instead of [TearDown] because the init function needs to await a frame passing
        // to ensure that the MRTK system has fully torn down before the next test setup->run cycle starts.
        [UnityTearDown]
        public IEnumerator TearDown()
        {
            PlayModeTestUtilities.TearDown();
            yield return null;
        }

        #region Tests

        /// <summary>
        /// Skeleton for a new MRTK play mode test.
        /// </summary>
        [UnityTest]
        public IEnumerator TestMyFeature()
        {
            // ----------------------------------------------------------
            // EXAMPLE PLAY MODE TEST METHODS
            // ----------------------------------------------------------
            // Getting the input system
            // var inputSystem = PlayModeTestUtilities.GetInputSystem();

            // Creating a new test hand for input
            // var rightHand = new TestHand(Handedness.Right);
            // yield return rightHand.Show(new Vector3(0, 0, 0.5f));

            // Moving the new test hand
            // We are doing a yield return here because moving the hand to a new position
            // requires multiple frames to complete the action.
            // yield return rightHand.MoveTo(new Vector3(0, 0, 2.0f));

            // Getting a specific pointer from the hand
            // var linePointer = PointerUtils.GetPointer<LinePointer>(Handedness.Right);
            // Assert.IsNotNull(linePointer);
            // ---------------------------------------------------------

            // Your new test here
            yield return null;
        }
        #endregion
    }
}
#endif

編集モード テスト

編集モードのテストは Unity の編集モードで実行され、Mixed Reality ツールキット リポジトリの [MRTK]>[テスト]>[EditModeTests] フォルダーに追加できます。 新しいテストを作成するには、次のテンプレートを使用できます。

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using NUnit.Framework;

namespace Microsoft.MixedReality.Toolkit.Tests
{
    class EditModeExampleTest
    {
        [Test]
        /// the name of this method will be used as test name in the unity test runner
        public void TestEditModeExampleFeature()
        {

        }
    }
}

テストの名前付け規則

テストは通常、テストするクラス、またはテストしているシナリオに基づいて名前を付ける必要があります。 たとえば、テスト対象のクラスがあるとします。

namespace Microsoft.MixedReality.Toolkit.Input
{
    class InterestingInputClass
    {
    }
}

テストの名前付けを検討する

namespace Microsoft.MixedReality.Toolkit.Tests.Input
{
    class InterestingInputClassTest
    {
    }
}

対応する非テスト ファイルに似たフォルダー階層にテストを配置することを検討します。 次に例を示します。

Non-Test: Assets/MRTK/Core/Utilities/InterestingUtilityClass.cs
Test: Assets/MRTK/Tests/EditModeTests/Core/Utilities/InterestingUtilityClassTest.cs

これは、各クラスの対応するテスト クラスが存在する場合に、そのようなテスト クラスを見つける明確な方法が存在することを確実にするためです。

シナリオ ベースのテストの配置はあまり定義されていません。たとえば、テストが入力システム全体で行われる場合は、対応する編集モードまたは再生モードのテスト フォルダー内にある "InputSystem" フォルダーに配置することを検討します。

テスト スクリプトのアイコン

新しいテストを追加する際には、正しい MRTK アイコンが含まれるようにスクリプトを変更してください。 そのための簡単な MRTK ツールがあります。

  1. [Mixed Reality ツールキット] メニュー項目に移動します。
  2. [ユーティリティ]、[更新]、[アイコン] の順にクリックします。
  3. [テスト] をクリックすると、アップデーターが自動的に実行され、アイコンが見つからないテスト スクリプトが更新されます。

MRTK ユーティリティ メソッド

このセクションでは、MRTK のテストを作成するときによく使用されるコード スニペットやメソッドの一部を示します。

MRTK の設定と、MRTK のコンポーネントの対話式操作のテストに役立つ 2 つのユーティリティ クラスがあります

TestUtilities には、MRTK シーンと GameObjects を設定するための次のメソッドが用意されています。

/// creates the mrtk GameObject and sets the default profile if passed param is true
TestUtilities.InitializeMixedRealityToolkit()

/// creates an empty scene prior to adding the mrtk GameObject to it
TestUtilities.InitializeMixedRealityToolkitAndCreateScenes();

/// sets the initial playspace transform and camera position
TestUtilities.InitializePlayspace();

/// destroys previously created mrtk GameObject and playspace
TestUtilities.ShutdownMixedRealityToolkit();

これらのユーティリティ クラスのその他のメソッドについては、TestUtilities および PlayModeTestUtilities の API ドキュメントを参照してください。これらは、新しいテストが MRTK に追加される間に定期的に拡張されます。