MSBUILD Run NCover Against Matched Projects

321 views Asked by At

I am using MSBuild and am getting all test projects using a regex on the project name, like this.

<RegexMatch Input="@(AllProjects)" Expression="(.)*Test(.)*">
    <Output  TaskParameter="Output" ItemName="UnitTestProjects"/>
</RegexMatch>

I now want to use @(UnitTestProjects) and pass them all to NCover to check that the tests are all giving 100% coverage.

To do this on a single project, I do something like this:

<Target Name="Coverage">
    <NCover TestRunnerExe="C:\Program Files\NUnit 2.5.8\bin\net-2.0\nunit-console.exe"
        TestRunnerArgs="&quot;C:\SomeProject\bin\SomeProject.dll&quot; &quot;C:\SomeProject\bin\SomeProjectTest.dll&quot;"
        WorkingDirectory="C:\SomeProject\bin\"
        AppendTrendTo="coverage.trend"
        OnlyAssembliesWithSource="True"
        ProjectName="SomeProjectCoverage"    />
</Target>

How do I effectively use @(UnitTestProjects) in the context of this NCover target?

1

There are 1 answers

6
Filburt On BEST ANSWER

For batching your @(UnitTestProjects) your Target will have to use it like this:

<Target Name="Coverage">
    <NCover TestRunnerExe="C:\Program Files\NUnit 2.5.8\bin\net-2.0\nunit-console.exe"
    TestRunnerArgs="&quot;%(UnitTestProjects.Identity)&quot; &quot;%(UnitTestProjects.Identity)&quot;"

<!--
If you receive the Task Output (*Test.dll) you will have to extract
the working dir path
-->
    WorkingDirectory="C:\SomeProject\bin\"
    AppendTrendTo="coverage.trend"
    OnlyAssembliesWithSource="True"
<!--
... the same thing applies to finding out the current project name
from your Task Ouput.
-->
    ProjectName="SomeProjectCoverage"    />
</Target>

A more reliable solution would be, to provide a list of TaskItems, holding metadata about your (Test)project.

<ItemGroup>
    <TestProject Include="MyProject1.Test.dll">
        <TestProjectName>MyProject1</TestProjectName>
        <MyTestProjectWorkingDir>C:\MyProject1\bin</MyTestProjectWorkingDir>
    </TestProject>
    <TestProject Include="MyProject2.Test.dll">
        <TestProjectName>MyProject2</TestProjectName>
        <MyTestProjectWorkingDir>C:\MyProject2\bin</MyTestProjectWorkingDir>
    </TestProject>
</ItemGroup>

<Target Name="Coverage">
    <NCover TestRunnerExe="C:\Program Files\NUnit 2.5.8\bin\net-2.0\nunit-console.exe"
    TestRunnerArgs="&quot;%(TestProject.Identity)&quot; &quot;%(TestProject.Identity)&quot;"
    WorkingDirectory="%(TestProject.MyTestProjectWorkingDir)"
    AppendTrendTo="coverage.trend"
    OnlyAssembliesWithSource="True"
    ProjectName="%(TestProject.MyTestProjectName)"    />
</Target>

Your question suggests that you are looking for an automated approach which will allow you to add new test projects without having to maintain a configuration list of TaskItems.

Since it would be quite difficult, to extract all the information needed to feed your NCover Task maybe a semi-automated approach might work for you.

You could add an import to your test project which will feed your global test project ItemGroup:

<ItemGroup>
    <!-- add existing ItemGroup -->
    <TestProject Include="@(TestProject)" />

    <!-- add project itself -->
    <TestProject Include="MyProject1.Test.dll">
        <TestProjectName>MyProject1</TestProjectName>
        <MyTestProjectWorkingDir>C:\MyProject1\bin</MyTestProjectWorkingDir>
    </TestProject>
</ItemGroup>

The usage in your NCover Task will be the same as above.

This way your master build script doesn't need to know about any specific test project; it just processes your ItemGroup "TestProject".