撰寫和執行測試 — MRTK2

為了確保 MRTK 可靠,MRTK 有一組測試,以確保程式碼的變更不會回歸現有的行為。 在 MRTK 之類的大型程式碼基底中擁有良好的測試涵蓋範圍,對於穩定性和在進行變更時擁有信心非常重要。

MRTK 使用 Unity 測試執行器 ,其使用 NUnit的 Unity 整合。 本指南將提供如何將測試新增至 MRTK 的起點。 它不會說明可在提供的連結中查閱 的 Unity 測試執行器和NUnit

提交提取要求之前,請務必:

  1. 在本機執行測試,讓您的變更不會在完成 PR (傳回現有的行為,如果有任何測試失敗,則不允許) 。

  2. 如果修正錯誤,請撰寫測試來測試修正,並確保未來的程式碼修改不會再次中斷。

  3. 如果撰寫功能,請撰寫新的測試,以防止即將發生的程式碼變更中斷此功能。

目前 playmode 測試是要在 Unity 2018.4 中執行,而且在其他版本的 Unity 中可能會失敗

執行測試

Unity 編輯器

Unity 測試執行器可以在[視窗>一般>測試執行器] 底下找到,並顯示所有可用的 MRTK 播放和編輯模式測試。

命令列

測試也可以由位於 Scripts\test\run_playmode_tests.ps1Powershell腳本執行。 這會執行 playmode 測試,就像是在 github / CI 上執行一樣, (請參閱下列) 和列印結果。 以下是如何執行腳本的一些範例

在位於 H:\mrtk.dev 的專案上執行測試,例如 Unity 2018.4.4 (,例如 Unity 2018.4.26f1)

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

在位於 H:\mrtk.dev 的專案上執行測試,使用 Unity 2018.4 將結果輸出至 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 腳本多次執行 Playmode 測試。 中所使用的 run_playmode_tests.ps1 所有參數都可以使用。

.\run_repeat_tests.ps1 -Times 5

提取要求驗證

MRTK 的 CI 將會在所有設定中建置 MRTK,並執行所有編輯和播放模式測試。 如果使用者有足夠的許可權,可以在 github PR /azp run mrtk_pr 上張貼批註來觸發 CI。 您可以在 PR 的 [檢查] 索引標籤中看到 CI 執行。

只有在成功通過所有測試之後,PR 才會合並成 main。

壓力測試/大量測試

有時候,測試偶爾只會失敗,而這可能會令人感到不小心偵錯。

若要在本機執行多個測試,請修改據以測試腳本。 下列 Python 腳本應該讓此案例更方便。

執行 Python 腳本的必要條件是 安裝 Python 3.X

針對需要多次執行的單一測試:

[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() {...}

開啟測試執行器,並觀察現在可以重複呼叫的新測試。

編寫測試

有兩種類型的測試可以針對新程式碼新增

  • 播放模式測試
  • 編輯模式測試

播放模式測試

MRTK 播放模式測試能夠測試新功能如何回應不同的輸入來源,例如手部或眼睛。

新的播放模式測試可以繼承 BasePlayModeTests ,或使用下列基本架構。

若要建立新的播放模式測試:

  • 流覽至 > 資產 MRTK > 測試 > PlayModeTests
  • 以滑鼠右鍵按一下 [建立 > 測試 > 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 Toolkit 存放庫中的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 中的元件互動

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();

請參閱 和 PlayModeTestUtilitiesTestUtilities API 檔,以取得這些公用程式類別的進一步方法,因為它們會定期擴充,同時將新的測試新增至 MRTK。