使用MSBuild,如何为列表中的每N个项运行Exec?

使用MSBuild,如何为列表中的每N个项运行Exec?,msbuild,mstest,Msbuild,Mstest,最初,我想从一个文件中加载一个测试列表,并在其自己的MSTest实例中调用每个测试。下面的脚本片段实现了这一点: <ReadLinesFromFile File="$(SolutionDir)\TestList.txt" > <Output TaskParameter="Lines" ItemName="TestsFromFile" /> </ReadLinesFromFile> <ItemGroup>

最初,我想从一个文件中加载一个测试列表,并在其自己的MSTest实例中调用每个测试。下面的脚本片段实现了这一点:

<ReadLinesFromFile
  File="$(SolutionDir)\TestList.txt" 
  >
  <Output
    TaskParameter="Lines"
    ItemName="TestsFromFile"
    />
</ReadLinesFromFile>

<ItemGroup>
  <Commands Include='&quot;$(VS100COMNTOOLS)\..\IDE\mstest.exe&quot; /runconfig:$(ParsedTestSettings) /testcontainer:$(ParsedTestContainer) /unique /test:%(TestsFromFile.Identity) /resultsfile:$(SolutionDir)\AnalysisResults\%(TestsFromFile.Identity).trx'/>
</ItemGroup>

<Exec
  Condition="'@(Tests)' != ''" 
  IgnoreExitCode="true"
  Command='%(Commands.Identity)'
  >
  <Output TaskParameter="exitcode" ItemName="exitcodes"/>
</Exec>


但是,假设不是每个测试执行一个mstest.exe实例,而是每10个测试或每N个测试执行一个mstest.exe实例。有没有办法让MSBuild为N个测试运行exec任务?

您可以创建自己的自定义生成任务并传入列表。很简单,在Execute()覆盖中,您只需在列表上循环并以任意频率生成MSTest。

您可以创建自己的自定义生成任务并传入列表。很简单,在Execute()覆盖中,您只需在列表上循环并以任意频率生成MSTest。

根据stijn的建议,下面是内联任务。请注意,GroupSize属性允许我控制每个Exec任务包含多少项

<UsingTask
  TaskName="GenerateTestOptionsCollection"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MicrosoftBuildTasksPath)"
  >
  <ParameterGroup>
    <SolutionDir
      ParameterType="System.String"
      Required="true"
      />
    <GroupSize
      ParameterType="System.Int32"
      Required="true"
      />
    <TestNames 
      ParameterType="Microsoft.Build.Framework.ITaskItem[]" 
      Required="true" 
      />
    <TestOptions
      ParameterType="Microsoft.Build.Framework.ITaskItem[]" 
      Output="true"
      />
  </ParameterGroup>
  <Task>
    <Code 
      Type="Fragment"
      Language="cs"
      >
      <![CDATA[
          var optionGroups = new List<string>();
          var optionItems = new List<TaskItem>();

          for (var j = 0; j < TestNames.Length; j++)
          {
              optionGroups.Add("/test:" + TestNames[j].ItemSpec);

              if (((j + 1) % GroupSize == 0) || j == (TestNames.Length - 1))
              {
                  var options = string.Join(" ", optionGroups) + " " + "/resultsfile:" + SolutionDir + "\\AnalysisResults\\" + optionItems.Count + ".trx";
                  optionItems.Add(new TaskItem(options));
                  optionGroups.Clear();
              }
          }

          TestOptions = optionItems.ToArray();
      ]]>
    </Code>
  </Task>
</UsingTask>

<代码
Type=“Fragment”
Language=“cs”
>
();
var optionItems=新列表();
对于(var j=0;j

使用内联任务:

<ReadLinesFromFile
  File="$(SolutionDir)\TestList.txt" 
  >
  <Output
    TaskParameter="Lines"
    ItemName="TestsFromFile"
    />
</ReadLinesFromFile>

<GenerateTestOptionsCollection
  SolutionDir="$(SolutionDir)"
  GroupSize="$(GroupSize)"
  TestNames="@(TestsFromFile)"
  >
  <Output ItemName="Commands" TaskParameter="TestOptions"/>
</GenerateTestOptionsCollection>

<Exec
  Condition="'@(Tests)' != ''" 
  IgnoreExitCode="true"
  Command='&quot;$(VS100COMNTOOLS)\..\IDE\mstest.exe&quot; /runconfig:$(ParsedTestSettings) /testcontainer:$(ParsedTestContainer) /unique %(Commands.Identity)'
  >
  <Output TaskParameter="exitcode" ItemName="exitcodes"/>
</Exec>

根据stijn的建议,下面是内联任务。请注意,GroupSize属性允许我控制每个Exec任务包含多少项

<UsingTask
  TaskName="GenerateTestOptionsCollection"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MicrosoftBuildTasksPath)"
  >
  <ParameterGroup>
    <SolutionDir
      ParameterType="System.String"
      Required="true"
      />
    <GroupSize
      ParameterType="System.Int32"
      Required="true"
      />
    <TestNames 
      ParameterType="Microsoft.Build.Framework.ITaskItem[]" 
      Required="true" 
      />
    <TestOptions
      ParameterType="Microsoft.Build.Framework.ITaskItem[]" 
      Output="true"
      />
  </ParameterGroup>
  <Task>
    <Code 
      Type="Fragment"
      Language="cs"
      >
      <![CDATA[
          var optionGroups = new List<string>();
          var optionItems = new List<TaskItem>();

          for (var j = 0; j < TestNames.Length; j++)
          {
              optionGroups.Add("/test:" + TestNames[j].ItemSpec);

              if (((j + 1) % GroupSize == 0) || j == (TestNames.Length - 1))
              {
                  var options = string.Join(" ", optionGroups) + " " + "/resultsfile:" + SolutionDir + "\\AnalysisResults\\" + optionItems.Count + ".trx";
                  optionItems.Add(new TaskItem(options));
                  optionGroups.Clear();
              }
          }

          TestOptions = optionItems.ToArray();
      ]]>
    </Code>
  </Task>
</UsingTask>

<代码
Type=“Fragment”
Language=“cs”
>
();
var optionItems=新列表();
对于(var j=0;j

使用内联任务:

<ReadLinesFromFile
  File="$(SolutionDir)\TestList.txt" 
  >
  <Output
    TaskParameter="Lines"
    ItemName="TestsFromFile"
    />
</ReadLinesFromFile>

<GenerateTestOptionsCollection
  SolutionDir="$(SolutionDir)"
  GroupSize="$(GroupSize)"
  TestNames="@(TestsFromFile)"
  >
  <Output ItemName="Commands" TaskParameter="TestOptions"/>
</GenerateTestOptionsCollection>

<Exec
  Condition="'@(Tests)' != ''" 
  IgnoreExitCode="true"
  Command='&quot;$(VS100COMNTOOLS)\..\IDE\mstest.exe&quot; /runconfig:$(ParsedTestSettings) /testcontainer:$(ParsedTestContainer) /unique %(Commands.Identity)'
  >
  <Output TaskParameter="exitcode" ItemName="exitcodes"/>
</Exec>

或者使用最新的msbuild,也可以这样做;或者使用最新的msbuild,也可以这样做