我可能在這裏問了一個錯誤的問題,我對此持開放態度,所以我將介紹一下我正在嘗試做的事情。在動態查找所有測試程序集後,我通過msbuild項目調用mstest。我爲每個測試程序集單獨調用mstest,以便結果可以在可用時立即導入到teamcity(我的CI服務器)中,而不是在TC顯示任何進度之前等待它們全部完成。Msbuild:將一個項目組轉換爲另一個具有不同結構的項目組
問題在於,它一次只運行一次測試,並且結合慢速開銷(即使在i7 quad上,mstest每個項目需要花費3-5秒的開銷)以及許多測試,測試需要幾分鐘後跑。
使用msbuild task與BuildInParallel = true(並使用/ m參數調用),可以一次構建多個項目。
那麼我現在要做的是
- 得到所有的列表* .Tests.dll
調用ExecMsTest目標在同一項目並行,每個.dll文件
<PropertyGroup> <MsTestExePath Condition="'$(MsTestExePath)'==''">C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe</MsTestExePath> <MsTestSettingsPath Condition="'$(MsTestSettingsPath)'==''">Project.testsettings</MsTestSettingsPath> </PropertyGroup> <ItemGroup> <TestAssemblies Include="**\bin\**\*.Tests.dll" /> </ItemGroup> <Target Name="RunTests"> <Message Text="Found test assemblies: @(TestAssemblies)" /> <MakeDir Directories="TestResults" /> <MsBuild Projects="@(ProjectsToBuild)" Targets="ExecMsTest" BuildInParallel="True" /> </Target> <Target Name="ExecMsTest"> <Message Text="Running tests in $(TestAssembly)" /> <!-- show TC progress --> <Message Text="##teamcity[progressMessage 'Running tests in $(TestAssembly).dll']" Importance="High" /> <PropertyGroup> <MsTestCommand>"$(MsTestExePath)" /testcontainer:"$(TestAssembly)" /resultsfile:"TestResults\$(TestAssembly).trx" /testsettings:"$(MsTestSettingsPath)"</MsTestCommand> </PropertyGroup> <!-- Message Text="Exec: $(MsTestCommand)"/--> <Exec Command="$(MsTestCommand)" ContinueOnError="true" /> <!-- import data to teamcity test results --> <Message Text="##teamcity[importData type='mstest' path='TestResults\$(TestAssembly).trx']" /> <Message Text="Tests complete from $(TestAssembly)" />
然而,這並不完全正確。你可以看到我的itemgroup被稱爲TestAssemblies,但是我將@(ProjectsToBuild)傳遞給mstest。這是因爲MSBuild任務需要不同格式的項目組,是這樣的:
<ItemGroup>
<ProjectsToBuild Include="Project.mstest.proj">
<Properties>TestAssembly=Project.UI.Tests</Properties>
</ProjectsToBuild>
<ProjectsToBuild Include="Project.mstest.proj">
<Properties>TestAssembly=Project.Model.Tests</Properties>
</ProjectsToBuild>
</ItemGroup>
所以這是我的問題的癥結所在,假設我甚至問正確的事情:我怎麼轉換TestAssemblies的ItemGroup成類似於ProjectsToBuild項目組的東西?
如果不明顯,TestAssemblies中的項目名稱就是* .tests.Dll文件名,而我需要該名稱作爲該項目的內部名稱,而ProjectsToBuild項目的名稱全部爲Project .mstest.proj文件(因爲它們都調用相同的文件)。
感謝@Spider M9,這個工程:
<ItemGroup>
<TestAssemblies Include="**\bin\**\*.Tests.dll" />
</ItemGroup>
<Target Name="RunTests">
<Message Text="Found test assemblies: @(TestAssemblies)" />
<ItemGroup>
<TestAssembliesToBuild Include="Project.mstest.proj">
<Properties>TestAssembly=%(TestAssemblies.FileName);FullPath=%(TestAssemblies.FullPath)</Properties>
</TestAssembliesToBuild>
</ItemGroup>
<MakeDir Directories="TestResults" />
<MsBuild Projects="@(TestAssembliesToBuild)" Targets="ExecMsTest" BuildInParallel="True" />
</Target>
運行的MSBuild單線程的,我的整個構建(包括編譯,構建應用程序和數據庫快照,部署模式的一對夫婦的數據庫是在一些單元測試中使用,然後最終運行mstest)花費了大約9分30秒。在這個變化之後,它花費了大約7米。
但是,在得到這個問題的答案之前,我試着運行一個單獨的mstest實例,看看它會改善多少,並且需要大約4分50秒(其中mstest需要稍微超過1分鐘才能運行)。缺點是我必須等到所有測試完成才能獲得結果,但考慮到從6m到1m的驚人改進,這是一個完全可以接受的平衡。
需要說明的是,唯一的區別是mstest只啓動一次,而開始十幾次,大概還有多任務的一些好處。我在Core i7-860(4個物理內核,8個邏輯內核)上運行這個程序,我懷疑內核數量會對這種改變帶來的改進程度產生很大影響。
這是我的新RunTests:
<Target Name="RunTests">
<Message Text="Found test assemblies: @(TestAssemblies)" />
<MakeDir Directories="TestResults" />
<!-- this executes mstest once, and runs all assemblies at the same time. Faster, but no output to TC until they're all completed -->
<PropertyGroup>
<MsTestCommand>"$(MsTestExePath)" @(TestAssemblies->'/testcontainer:"%(FullPath)"', ' ') /resultsfile:"TestResults\Results.trx" /testsettings:"$(MsTestSettingsPath)"</MsTestCommand>
</PropertyGroup>
<Message Text="##teamcity[progressMessage 'Running tests']" Importance="High" />
<Message Text="Exec: $(MsTestCommand)" />
<Exec Command="$(MsTestCommand)" ContinueOnError="true" />
<Message Text="##teamcity[importData type='mstest' path='TestResults\Results.trx']" />
</Target>
也,你需要一個testsettings與文件:<Execution parallelTestCount="0">
(0表示自動檢測,默認爲1),但需要使用/m
參數和/或<Msbuild BulidInParallel="true">
這讓我在正確的軌道上。我已經將TestAssemblies定義爲全局項目組,並且TestAssembliestoBuild不能在同一個項目組中定義,但是如果它位於任務內的項目組內部,它就會工作。之後,這工作很好。 – gregmac 2011-04-06 17:34:25