Thursday, September 10, 2009

Executing PartCover from NAnt

I wanted to replace NCover with PartCover. PartCover is a new code coverage tool, and its still a freeware.

With NCover I had to run NUnit twice, first to get the unit test results, and then another run to get the code coverage. (At least with the last freeware version of NCover, 1.5.8. I have not tried the commercial versions)

With PartCover its possible to run the tests AND get the coverage at the same time.

Another advantage is that I can use newer versions of NUnit. The NCover 1.5.8 does not work with NUnit from version 2.5.

It seemed rather easy, but I had problems with quotes in the NAnt build file. The PartCover always terminated with an exception, whatever I tried; quotes, variables, expressions:

Invalid option '--target=C:\Program Files\NUnit 2.4.5\bin\nunit-console.exe'

One work-around is to use a NUnit or PartCover configuration file, but I wanted the NAnt build file to be independent.

The solution was to use HTML character entity references, i.e. a double quote (“) can be written as ".

Example of NAnt target that executes PartCover which in turn produces both a coverage report and a unit test report in a specified folder:

  <target name="unitTest">

    <!-- Get all unit test assemblies -->
    <foreach item="File" property="filename">
      <in>
        <items basedir=".">
          <include name="${Build.Output}\bin\${MyProject}.Test.dll"></include>
          <include name="${Build.Output}\bin\${MyProject}.*.Test.dll"></include>
        </items>
      </in>
      <do>

        <echo message="Unittesting ${filename}"/>

        <exec program="${PartCoverHome}\Partcover.exe" failonerror="true">
          <arg line="--target &quot;${NUnitExePath}&quot;" />
          <arg line="--target-work-dir ${Build.Output}\bin"/>
          <arg line="--target-args &quot;${filename} /xml=${Build.Reports}\${path::get-file-name-without-extension(filename)}-UnitTest.xml&quot;" />
          <arg line="--include [${MyProject}.*]*" />
          <arg line="--exclude [${MyProject}.*Test*]*" />
          <arg line="--output ${Build.Reports}\${path::get-file-name-without-extension(filename)}-Coverage.xml" />
        </exec>
      </do>
    </foreach>
  </target>  

6 comments:

  1. Nice job, someone should write nunit task for PartCover.

    ReplyDelete
  2. Thanks!
    A PartCover task would be great.

    TeamCity version 5 has support for PartCover (and NCover), it simplifies the generation and presentation.

    ReplyDelete
  3. I found this gotcha. This is command line stuff.

    NOTICE that it is not

    --target="C:\Program Files\NUnit 2.5.2\bin\net-2.0\nunit-console.exe"

    But rather:
    --target "C:\Program Files\NUnit 2.5.2\bin\net-2.0\nunit-console.exe"

    Aka, no "=" (equal sign)

    This PLAGUED ME FOR HOURS!!!

    Here is a full mini sample:

    "C:\Program Files\WhereIHavePartCover\PartCover.exe" --target "C:\Program Files\NUnit 2.5.2\bin\net-2.0\nunit-console.exe" --output="c:\MyDirectory With A Space In It\SubDirectoryForResults\PartCover_RESULTS.xml" --target-work-dir "c:\MyDirectory With A Space In It" --target-args "MyAssembly.dll"

    I hope this comment/posting system does not strip anything from my comment.

    This is contrary to the documentation that comes with the PartCover download. Namely the "PartCover Console Manual.rtf" file. It has the equal sign in it.

    NOW, that prevents the "Invalid option" error from popping up.......but I'm still not getting any results in my PartCover_RESULTS.xml file. So my post might be a goose-chaser. But I figured I would post this before closing my browser and forgetting about it.

    PS
    Here is a MSBuild Task for those who do not use nant
    http://www.zorched.net/2009/01/08/msbuild-task-for-partcover/

    ReplyDelete
  4. PartCover needs to know which namespaces and classes to include in the coverage, for example, "--include [*]*", includes all classes in all namespaces (RegExp syntax).

    That will probably fix the empty report.

    ReplyDelete
  5. Thank you! The HTML encoding for quotes was what FINALLY did this for me after hours of frustration.

    ReplyDelete