February 8, 2014

與Jenkins共舞 - 自動化測試整合

與Jenkins共舞 - 建置Visual Studio專案中,我們成功地讓Jenkins建置Visual Studio專案,然而這只是在做持續整合最基本的一項要求。在成功建置程式碼後,就可以開始導入更進階的整合功能,例如自動化測試。本篇文章將介紹如何設定Jenkins來執行專案中的測試程式,並顯示測試結果。

安裝NUnit
由於我主要是以NUnit來撰寫測試程式,所以安裝NUnit以便讓Jenkins呼叫NUnit來執行測式程式。至http://www.nunit.org/index.php?p=download下載NUnit並解壓縮至特定路徑如C:\tools\NUnit-2.6.3。


安裝MSBuild Extension Pack
MSBuild Extension Pack提供大量的MSBuild Task,其中就含有執行NUnit的Task並產生測試結果。至http://msbuildextensionpack.codeplex.com/下載MSBuild Extension Pack。


這邊下載的是MSBuild Extension Pack 4.0版本,因為我的專案是由.NET 4.0所開發。下載後解壓縮後可以看到還有3個壓縮檔,分別是MSBuild Extension Pack 4.0.8.0 Binaries.zipMSBuild Extension Pack 4.0.8.0 Help.zipMSBuild Extension Pack 4.0.8.0 Installers.zip。將MSBuild Extension Pack 4.0.8.0 Installers.zip解壓縮並安裝其中的MSBuild Extension Pack 4.0.msi。安裝後可以在C:\Program Files (x86)\MSBuild\ExtensionPack\4.0路徑下看到MSBuild Extension Pack所提供的函式庫。當然你也可以直接將MSBuild Extension Pack 4.0.8.0 Binaries.zip解壓縮後放置到相同的路徑下。



建立Targets檔案
接下來我們建立一份NUnit.targets檔案(檔案名稱可自訂),這份檔案的內容格式為XML。
<Project ToolsVersion="4.0" DefaultTargets="NUnit" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks" Condition="Exists('$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks')" />
    <PropertyGroup>
        <ToolPath>C:\tools\NUnit-2.6.3\bin</ToolPath>
    </PropertyGroup>
    <Target Name="NUnit">
        <ItemGroup>
            <Assemblies Include="$(MSBuildStartupDirectory)\src\Demo\Demo.Service.IntegrationTests\bin\Release\*.dll" />
        </ItemGroup>
        <!--- Run NUnit over a collection of assemblies -->
        <MSBuild.ExtensionPack.CodeQuality.NUnit Assemblies="@(Assemblies)" ToolPath="$(ToolPath)" OutputXmlFile="$(MSBuildStartupDirectory)\NUnit.xml">
            <Output TaskParameter="Total" PropertyName="ResultTotal" />
            <Output TaskParameter="NotRun" PropertyName="ResultNotRun" />
            <Output TaskParameter="Failures" PropertyName="ResultFailures" />
            <Output TaskParameter="Errors" PropertyName="ResultErrors" />
            <Output TaskParameter="Inconclusive" PropertyName="ResultInconclusive" />
            <Output TaskParameter="Ignored" PropertyName="ResultIgnored" />
            <Output TaskParameter="Skipped" PropertyName="ResultSkipped" />
            <Output TaskParameter="Invalid" PropertyName="ResultInvalid" />
        </MSBuild.ExtensionPack.CodeQuality.NUnit>
        <Message Text="ResultTotal: $(ResultTotal)" />
        <Message Text="ResultNotRun: $(ResultNotRun)" />
        <Message Text="ResultFailures: $(ResultFailures)" />
        <Message Text="ResultErrors: $(ResultErrors)" />
        <Message Text="ResultInconclusive: $(ResultInconclusive)" />
        <Message Text="ResultIgnored: $(ResultIgnored)" />
        <Message Text="ResultSkipped: $(ResultSkipped)" />
        <Message Text="ResultInvalid: $(ResultInvalid)" />
    </Target>
</Project>

以上有幾點需注意
  1. $(MSBuildExtensionsPath)\ExtensionPack\4.0\為MSBuild Extension Pack的安裝路徑,$(MSBuildExtensionsPath)指的則是MSBuild的預設位置,如C:\Program Files (x86)\MSBuild。
  2. C:\tools\NUnit-2.6.3\bin為NUnit執行檔路徑。
  3. $(MSBuildStartupDirectory)\src\Demo\Demo.Service.IntegrationTests\bin\Release\*.dll為測試程式執行時所有會使用到的函式庫,基本上就是指向測試專案產出的bin資料夾下所有的DLL檔案。$(MSBuildStartupDirectory)為呼叫MSBuild的目錄路徑,此一路徑為所執行的Build Job下的workspace路徑,如C:\Jenkins\jobs\Demo\workspace。
  4. $(MSBuildStartupDirectory)\NUnit.xml為測試結果的輸出路徑,此檔案將被Jenkins讀取做為測試結果報表的呈現。
我們將NUnit.targets放在Jenkins所設定的workspace路徑下,如C:\Jenkins\jobs\Demo\workspace\NUnit.targets。Demo在這裡指的是在Jenkins中建立的Job名稱。


安裝Jenikns NUnit Plugin
最後一個步驟就是讓Jenkins能執行測試專案,讀取測試結果並呈現出報表。這裡我們將借助於Jenkins NUnit Plugin。至Plugin Manager中安裝Jenkins NUnit Plugin。


安裝完成後,在Build Job內新增一個Build如下,且這個Build要放在建置專案的Build之後,如此才能確保測試是在專案能成功地建置之後才執行的。


接著在Post-build Actions中加入Publish NUnit test result report,讓Jenkins能讀取到測試結果。


設定完成後執行Build Job,即可看到測試結果報表。



值得注意是,當測試不通過時,Build Job是亮黃燈(Unstable)而不是紅燈(Failed)。


參考
  1. MSBuild Extension Pack Online Help
  2. MSBuild Reserved and Well-Known Properties

No comments: