13

How can I run a certain cleanup task after my "Test" target runs, regardless of whether the Test target succeeded or failed (like the try...finally construct in C#/Java).

ripper234
  • 222,824
  • 274
  • 634
  • 905

2 Answers2

14

The Target element has an OnError attribute you could set to a target to execute on error, but as it only executes if the target is in error, it only solves half your scenario.

Have you considered chaining together targets to represent the test 'steps' you'd like to execute?

<PropertyGroup>
    <TestSteps>TestInitialization;Test;TestCleanup</TestSteps>
</PropertyGroup>

The 'TestInitialization' target is where you can perform any test initialization, the 'Test' target executes the test, the 'TestCleanup' target does any sort of post test clean up.

Then, execute these targets using the CallTarget task, using the RunEachTargetSeparately attribute set to True. This will execute all the targets, regardless of success or failure.

The complete sample is below:

<Project DefaultTargets = "TestRun"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

    <!-- Insert additional tests between TestInitialization and TestCleanup as necessary -->
    <PropertyGroup>
        <TestSteps>TestInitialization;Test;TestCleanup</TestSteps>
    </PropertyGroup>

   <Target Name = "TestRun">

      <CallTarget Targets="$(TestSteps)" RunEachTargetSeparately="True" />

   </Target>

    <Target Name = "TestInitialization">
        <Message Text="Executing Setup..."/>
    </Target>

    <Target Name = "Test">
        <Message Text="Executing Test..."/>

        <!-- this will fail (or should unless you meet the conditions below on your machine) -->
        <Copy 
          SourceFiles="test.xml"
          DestinationFolder="c:\output"/>
    </Target>

    <Target Name = "TestCleanup">
        <Message Text="Executing Cleanup..."/>
    </Target>

</Project>
Zach Bonham
  • 6,759
  • 36
  • 31
  • Just came to testing this now, and it works perfectly. Thanks for the rather complete example. – ripper234 Oct 07 '09 at 15:28
  • 1
    Good answer, though it would be good to know how to 'rethrow', to continue the try/finally analogy. Cleanup may need to execute no matter what, but the build still fail. – Sebastian Good May 04 '12 at 17:15
  • I'm confused: I thought the way to 'rethrow' is simply to use the `OnError` attribute in an _overridden_ CoreBuild target. You can define the the target to execute on error, and that will always run if the build fails, and you still get notified that the build failed. – Dave May 18 '12 at 15:48
0

Or use <OnError> to call your target in the error case, and DependsOnTargets or CallTarget to call your same target in the normal case.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249