MsBuild:如何传递一个带有CallTarget的ItemGroup

6
我在使用MSBuild脚本时遇到了一些关于项目组范围的问题。基本上,我想要创建两个不同的目标 - 让我们称它们为RunUnitTestsRunIntegrationTests - 生成一个名为TestAssemblies的项目组,然后调用RunTests,该目标使用TestAssemblies来确定从哪些程序集运行测试。
单元测试和集成测试的两个不同目标都依赖于构建目标,并从那里获取所有已编译的程序集的项目组,但由于RunTests目标将从不同的位置调用,因此它实际上不能依赖于其中任何一个。因此,我需要以某种方式将项目组传递给通用的测试运行器目标。然而,这似乎是不可能的,因为在目标中更改项目组似乎仅适用于该目标内部。
我看到了这些帖子(链接)(链接),但它们只是确认了我的担忧,并建议DependsOnTarget作为解决方法 - 但这对我来说行不通,因为我需要在不同的运行中从不同的位置获取项目组。
以下是我目前的代码:
<Target Name="RunAllTests" DependsOnTarget="BuildProject">
    <!-- In here, items created in BuildProject are available. -->
    <CallTarget Targets="RunUnitTests;RunIntegrationTests">
</Target>

<Target Name="RunUnitTests" DependsOnTarget="BuildProject">
    <!-- In here, items created in BuildProject are available. -->
    <!-- One of those is @(UnitTestAssemblies) -->

    <CreateItem Include="@(UnitTestAssemblies)">
        <Output TaskParameter="Include" ItemName="TestAssemblies" />
    </CreateItem>

    <CallTarget Targets="RunTests" />
</Target>

<!-- Then there's a similar target named RunIntegrationTests, which does the
     same as RunUnitTests except it includes @(IntegrationTestAssemblies) -->

<Target Name="RunTests">
    <!-- Here, I'd like to access @(TestAssemblies) and pass them to the NUnit
         task, but they have fallen out of scope. -->
</Target>

有没有其他解决方案,或者我必须完全重构我的构建脚本?


@Thomas Gerstendörfer:请查看我的更新,其中包含我当前构建脚本的简化版本。 - Tomas Aschan
2个回答

14

在目标内部对项目组进行更改后,只有在更改目标退出后,其他目标才能看到更改。因此,为了使测试程序集列表保持不变,您可能需要将设置目标的实际操作移动到其自己的目标中,如下所示:

<Target Name="PrepareUnitTestList" DependsOnTarget="BuildProject">
  <ItemGroup>
    <TestAssemblies Include="@(UnitTestAssemblies)"/>
  </ItemGroup>
</Target>

<Target Name="RunUnitTests" DependsOnTargets="PrepareUnitTestList">
  <CallTarget Targets="RunTests"/>
</Target>

<Target Name="RunTests">
  <Message Text="Test: %(TestAssemblies.Identity)"/>
</Target>

通过一些重新组织,我成功地解决了这个问题。谢谢! - Tomas Aschan
也许您可以通过重新构造来改进这个答案... 我非常确定 RunTests 只被调用了一次,而 Message 每个 TestAssembly 都被调用了一次。 - Jeff Martin

2
在“MSBuild”任务中,您可以向目标传递属性,但我不确定它是否适用于ItemGroup。但是,您绝对可以通过批处理来实现 - 一次传递一个程序集。
<Target Name="RunUnitTests">
  <MSBuild Projects="$(MSBuildProjectFullPath)" Targets="RunTests" Properties="TestAssemblies=%(TestAssemblies.Identity)"/>
</Target>

它一次只能运行一个程序集的“RunTests”,因此如果您需要在运行测试时了解其他程序集的知识,则它将无用。但是也许它会给出一些更好的解决此问题的思路...


我考虑过这个问题,但同时也意识到我想要测试结果的总体收集,而不仅仅是每个组件的收集,所以这不是一个选项。 - Tomas Aschan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接