Showing posts with label msbuild. Show all posts
Showing posts with label msbuild. Show all posts

Sunday, December 28, 2008

Running unit tests during builds in Visual Studio .NET - part 2

Hi all,

as I've mentioned in my previous post it's quite easy to implement running tests during build process of VisualStudio. Now not everyone is comfortable with using a set of 3rd party tasks to do simple things. This time we're going to simplify things a little bit and use the Exec task of MSBuild that already comes with the standard installation.

We're going to start as previously with the XML style sheet that will convert the XML output to a format that's understandable by VisualStudio. Save the following content into your project under VSTestFormat.xslt:


<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='text'/>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="test-results">
<xsl:apply-templates select="//test-case[failure]"/>
</xsl:template>

<xsl:template match="test-case">
<xsl:value-of select="substring-before(substring-after(failure/stack-trace, ' in '), ':line')"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="normalize-space(substring-after(substring-after(failure/stack-trace, ' in '), ':line '))"/>
<xsl:text>)</xsl:text>
<xsl:text> : warning NU001: </xsl:text>
<xsl:value-of select="@name"/><xsl:text>: </xsl:text>
<xsl:value-of select="normalize-space(child::node()/message)" />
<xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>
</xsl:template>
</xsl:stylesheet>


Next we're going to add the task after building the project (that goes into the [projectname].csproj file):


<Target Name="AfterBuild">
<Exec Command='"$(ProgramFiles)\Nunit 2.4.8\bin\nunit-console.exe" $(OutputPath)$(AssemblyName).dll /xml=$(OutputPath)nunit-results.xml /transform=VSTestFormat.xslt /noshadow /nologo /nodots' />
</Target>


That's it! Now when you'll build your project it is going to run tests before returning to the editor and all failing tests are converted to a list of entries in the "Error List" window of VisualStudio.

Let me make one note here: This solution works perfectly with all IDEs - the full-blown one as well as with Express editions.

For those that don't like to experiment and just want to start building tests here's a VisualStudio template ready to use. Please note that it's provided "AS-IS" without any warranty so use it at your own risk.

NUnitTests.zip

Happy building!

Tuesday, December 23, 2008

Running unit tests during builds in Visual Studio .NET

Hi there,

Some time ago I've attended a refactoring training provided by my employer. One of the interesting things there was that the project we worked on had unit tests hooked up to the build process. Now that I'm learning the .NET platform and the tools that come with it I've decided to give it a try and to integrate NUnit into the build process of a class library.

Visual Studio creates its projects in MSBuild format. That means that we can customize/extend the build process in a standard fashion as MSBuild is the standard tool (aside from NAnt) used to build .NET projects.

Here are the steps I took to enable such integration:

  1. Install NUnit (this procedure assumes the version 2.4.8 - note the version in ToolPath parameter of NUnit task).
  2. Install MSBuild community tasks (http://msbuildtasks.tigris.org/)
  3. Add the following lines to your class library project (.csproj) with tests (output file must be named "something.Tests.dll")

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <ItemGroup>
    <TestAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
    </ItemGroup>
    <Target Name="AfterBuild">
    <NUnit Assemblies="@(TestAssemblies)" ToolPath="$(ProgramFiles)\Nunit 2.4.8\bin\" XsltTransformFile="vsfmt.xslt" OutputXmlFile="$(OutputPath)\nunit-results.xml"/>
    </Target>

  4. Copy the following content into vsfmt.xslt in your test project path or somewhere else (remember to modify XsltTransformFile parameter if you store it somewhere else):

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method='text'/>

    <xsl:template match="/">
    <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="test-results">
    <xsl:apply-templates select="//test-case[failure]"/>
    </xsl:template>

    <xsl:template match="test-case">
    <xsl:value-of select="substring-before(substring-after(failure/stack-trace, ' in '), ':line')"/>
    <xsl:text>(</xsl:text>
    <xsl:value-of select="normalize-space(substring-after(substring-after(failure/stack-trace, ' in '), ':line '))"/>
    <xsl:text>)</xsl:text>
    <xsl:text> : warning NU001: </xsl:text>
    <xsl:value-of select="@name"/><xsl:text>: </xsl:text>
    <xsl:value-of select="normalize-space(child::node()/message)" />
    <xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>
    </xsl:template>
    </xsl:stylesheet>

  5. Switch to VS - a dialog should appear that the project file has changed. Click "Reload".
  6. Rebuild solution - if there are any test cases they'll get executed as part of the build process.
  7. (optional) Add the following parameter to NUnit task if you don't want your unit tests to fail the build but rather to issue warnings:
    ContinueOnError="true"

    For example:

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <ItemGroup>
    <TestAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
    </ItemGroup>
    <Target Name="AfterBuild">
    <NUnit ContinueOnError="true" Assemblies="@(TestAssemblies)" ToolPath="$(ProgramFiles)\Nunit 2.4.8\bin\" XsltTransformFile="vsfmt.xslt" OutputXmlFile="$(OutputPath)\nunit-results.xml"/>
    </Target>

Remember that using this kind of integration with unit testing framework forces developers to create unit tests that are really fast. Nobody likes to wait for the build process to complete.

While working on this integration I've used the following pages as references:

http://blogs.msdn.com/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx
http://www.w3.org/TR/xpath#section-String-Functions
http://blog.maartenballiauw.be/category/NUnit.aspx
http://www.nunit.org
http://msbuildtasks.tigris.org


Happy building!