Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MsBuild: Passing an ItemGroup with CallTarget

I'm having some problems witht the scoping of item groups I create in an MSBuild script. Basically, what I want to do is to have two different targets - let's call them RunUnitTests and RunIntegrationTests - that generate an item group called TestAssemblies and then call RunTests, which uses TestAssemblies to determine which assemblies to run tests from.

The two different targets for unit and integration tests both depend on the build target and get an item group with all compiled assemblies from there, but since the RunTests target will be called from different places, it can't really depend on either of them. Thus, I need to pass the item group to the common testrunner target somehow. However, this seems to be impossible, because changes to an item group within a target seems to be scoped to only work within that target.

I've seen these posts, but they only seem to confirm my fears, and suggest DependsOnTarget as a workaround - which won't work for me, since I need to get the items from different places on different runs.

This is what I have so far:

<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>

Is there any way around this, or will I have to completely restructure my build script?

like image 833
Tomas Aschan Avatar asked Jul 18 '11 09:07

Tomas Aschan


2 Answers

Changes to an item group within a target are only visible to other targets after the changing target exits. So to get the list of test assemblies to stick, you may have to move actually setting up the targets to its own target as in the following:

<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>
like image 143
Thomas Gerstendörfer Avatar answered Sep 20 '22 17:09

Thomas Gerstendörfer


In "MSBuild" task you can pass properties to targets, but I'm not sure if it will work for ItemGroup. But you definitely can do it through batching - passing one assembly at a time.

<Target Name="RunUnitTests">
  <MSBuild Projects="$(MSBuildProjectFullPath)" Targets="RunTests" Properties="TestAssemblies=%(TestAssemblies.Identity)"/>
</Target>

It would run the "RunTests" for only one assembly at a time, so it will be useless if you need knowledge of other assemblies at time of running tests. But maybe it will give some better ideas how to resolve this problem...

like image 44
Damian Zarębski Avatar answered Sep 21 '22 17:09

Damian Zarębski