Share via


教學課程:測試自訂工作

您可以在散發之前,先使用 Visual Studio 中的單元測試功能來測試 MSBuild 自訂工作,以確保程式碼的正確性。 如需執行測試和基本測試控管的優點相關資訊,請參閱單元測試的基本概念。 在本教學課程中,您會使用其他 MSBuild 自訂工作教學課程中使用的程式碼範例。 這些教學課程中使用的下列專案可在 GitHub 中使用,並包含 MSBuild 自訂工作的單元和整合測試:

單元測試

MSBuild 自訂工作是繼承自 Task 的類別 (直接或間接,因為 ToolTask 繼承自 Task)。 執行與工作相關聯之動作的方法為 Execute()。 此方法會採用一些輸入值 (參數),且具有您可使用判斷提示來測試有效性的輸出參數。 在此情況下,有些輸入參數是檔案的路徑,所以此範例在名為 Resources 的資料夾中具有測試輸入檔案。 此 MSBuild 工作也會產生檔案,因此測試會判斷提示所產生的檔案。

需要建置引擎,這是實作 IBuildEngine 的類別。 在此範例中,有使用 Moq 的模擬,但您可使用其他模擬工具。 此範例會收集錯誤,但您可收集其他資訊,然後予以判斷提示。

所有測試都需要 Engine 模擬,所以會包含為 TestInitialize (它會在每個測試之前執行,而且每個測試都有自己的建置引擎)。

如需完整的程式碼,請參閱 GitHub 上 .NET 範例存放庫中的 AppSettingStronglyTypedTest.cs

  1. 建立工作,並將參數設定為測試排列的一部分:

        private Mock<IBuildEngine> buildEngine;
        private List<BuildErrorEventArgs> errors;
    
         [TestInitialize()]
         public void Startup()
         {
             buildEngine = new Mock<IBuildEngine>();
             errors = new List<BuildErrorEventArgs>();
             buildEngine.Setup(x => x.LogErrorEvent(It.IsAny<BuildErrorEventArgs>())).Callback<BuildErrorEventArgs>(e => errors.Add(e));
         }
    
  2. 建立 ITaskItem 參數模擬 (使用 Moq),並指向要剖析的檔案。 然後,使用其參數建立 AppSettingStronglyTyped 自訂工作。 最後,將建置引擎設定為 MSBuild 自訂工作:

    //Arrange
    var item = new Mock<ITaskItem>();
    item.Setup(x => x.GetMetadata("Identity")).Returns($".\\Resources\\complete-prop.setting");
    
    var appSettingStronglyTyped = new AppSettingStronglyTyped { SettingClassName = "MyCompletePropSetting", SettingNamespaceName = "MyNamespace", SettingFiles = new[] { item.Object } };
    
    appSettingStronglyTyped.BuildEngine = buildEngine.Object;
    

    然後,執行工作程式碼以執行實際的工作動作:

     //Act
     var success = appSettingStronglyTyped.Execute();
    
  3. 最後,判斷提示測試的預期結果:

    //Assert
    Assert.IsTrue(success); // The execution was success
    Assert.AreEqual(errors.Count, 0); //Not error were found
    Assert.AreEqual($"MyCompletePropSetting.generated.cs", appSettingStronglyTyped.ClassNameFile); // The Task expected output
    Assert.AreEqual(true, File.Exists(appSettingStronglyTyped.ClassNameFile)); // The file was generated
    Assert.IsTrue(File.ReadLines(appSettingStronglyTyped.ClassNameFile).SequenceEqual(File.ReadLines(".\\Resources\\complete-prop-class.txt"))); // Assenting the file content
    
  4. 其他測試會遵循此模式並展開所有可能性。

注意

產生檔案時,您必須對每項測試使用不同的檔名,以避免發生衝突。 請記得刪除所產生的檔案作為測試清除。

整合測試

單元測試很重要,但您也需要在實際建置內容中測試自訂 MSBuild 工作。

System.Diagnostics.Process Class 提供對本機和遠端處理序的存取,並讓您能夠啟動和停止本機系統處理序。 此範例會使用測試 MSBuild 檔案在單元測試上執行組建。

  1. 測試程式碼需要初始化每個測試的執行內容。 請注意,確定 dotnet 命令的路徑對您的環境而言是正確的。 完整範例在這裡

         public const string MSBUILD = "C:\\Program Files\\dotnet\\dotnet.exe";
    
         private Process buildProcess;
         private List<string> output;
    
         [TestInitialize()]
         public void Startup()
         {
             output = new List<string>();
             buildProcess = new Process();
             buildProcess.StartInfo.FileName = MSBUILD;
             buildProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
             buildProcess.StartInfo.CreateNoWindow = true;
             buildProcess.StartInfo.RedirectStandardOutput = true;
         }
    
  2. 在清除時,測試必須完成程序:

        [TestCleanup()]
         public void Cleanup()
         {
             buildProcess.Close();
         }
    
  3. 現在,建立每個測試。 每個測試都需要執行自己的 MSBuild 檔案定義。 例如,testscript-success.msbuild。 若要瞭解檔案,請參閱教學課程:建立自訂工作

    <Project Sdk="Microsoft.NET.Sdk">
        <UsingTask TaskName="AppSettingStronglyTyped.AppSettingStronglyTyped" AssemblyFile="..\AppSettingStronglyTyped.dll" />
        <PropertyGroup>
            <TargetFramework>netstandard2.1</TargetFramework>
        </PropertyGroup>
    
        <PropertyGroup>
            <SettingClass>MySettingSuccess</SettingClass>
            <SettingNamespace>example</SettingNamespace>
        </PropertyGroup>
    
        <ItemGroup>
            <SettingFiles Include="complete-prop.setting" />
        </ItemGroup>
    
        <Target Name="generateSettingClass">
            <AppSettingStronglyTyped SettingClassName="$(SettingClass)" SettingNamespaceName="$(SettingNamespace)" SettingFiles="@(SettingFiles)">
                <Output TaskParameter="ClassNameFile" PropertyName="SettingClassFileName" />
            </AppSettingStronglyTyped>
        </Target>
    </Project>
    
  4. 測試引數會提供建置此 MSBuild 檔案的指示:

     //Arrange
     buildProcess.StartInfo.Arguments = "build .\\Resources\\testscript-success.msbuild /t:generateSettingClass";
    
  5. 執行並取得輸出:

    //Act
    ExecuteCommandAndCollectResults();
    

    其中 ExecuteCommandAndCollectResults() 定義為:

    private void ExecuteCommandAndCollectResults()
    {
         buildProcess.Start();
         while (!buildProcess.StandardOutput.EndOfStream)
         {
             output.Add(buildProcess.StandardOutput.ReadLine() ?? string.Empty);
         }
         buildProcess.WaitForExit();
    }
    
  6. 最後,評估預期結果:

    //Assert
    Assert.AreEqual(0, buildProcess.ExitCode); //Finished success
    Assert.IsTrue(File.Exists(".\\Resources\\MySettingSuccess.generated.cs")); // the expected resource was generated
    Assert.IsTrue(File.ReadLines(".\\Resources\\MySettingSuccess.generated.cs").SequenceEqual(File.ReadLines(".\\Resources\\testscript-success-class.txt"))); // asserting the file content
    

結論

單元測試很有用,因為您可測試及偵錯程式碼,以確保每個特定程式碼片段的正確性,但具有整合測試很重要,可確保工作在實際組建內容中執行。 在本教學課程中,您已了解如何測試 MSBuild 自訂工作。

下一步

建立更複雜的自訂工作,以產生 REST API 程式碼。