Out of the box, Visual Studio 2005 Team Edition for Developers gives you the ability to create and run unit tests. Microsoft Team Foundation Server gives you the ability to create automated builds integrating work items, reporting, build quality and unit testing. But ONLY if you have the full Team System edition of Visual Studio, or at the very least, Visual Studio Team Edition for Testers.
That's because you need the ability to edit and organise test metadata files (VSMDI files). These pesky little things are what is needed to use the point-and-click unit test integration features on Team Foundation Build - the automated build part of TFS. But I don't have that, and nor do lots of other people. Luckily, Buck Hodges of the Team Foundation Server Team posted a workaround, which allows you to run all unit tests in an assembly, and to match assemblies to be tested with wildcards.
The post on how to do this is
here. The linked page supplies a download which has some instructions, an extended tools assembly, and a new .targets file.
If you were asleep during the lecture on 'targets' files, they are the templates that MSBuild uses to hide complex functionality - kind of like build include files. The particular target file specifies all the tasks necessary to run a TFS build. The replacement file integrates the no-vsmdi build tasks so that you can run all unit tests with a build. It works well, and is required bookmarking and posting for all.
However, for me, when unit testing failed, it didn't create a work item for the build failure like it does for a compile failure. I like the 'build has failed' bugs to be created because it is a nagging reminder to get in and fix the build, and keeps metrics on the number of build failures over time. So I really wanted a bug work item to be created when unit tests failed.
It looked like all was lost until I figured out (from a comment field in a post
here). It described the need to override the base .targets file behaviour because by default, a build failure wasn't triggered on a unit test failure.
So I copied out the entire RunTestWithConfiguration target from the Microsoft.TeamFoundation.Build.targets file that I obtained from Buck Hodges' post, and changed all the ContinueOnError attributes to 'true' from 'false'. I also added in a new OnError handler, and a new Target specifically for Unit Test failures.
The new OnError Handler in the RunTestWIthConfiguration target looks like this:
<OnError ExecuteTargets="UnitTestFailure"/>
Then I added in a new target and property group for 'UnitTestFailure'
<PropertyGroup>
<OnUnitTestFailureDependsOn> BeforeUnitTestFail; CreateWorkItem; AfterUnitTestFail; OnUnitTestFailureDependsOn>
PropertyGroup>
<Target Name ="UnitTestFailure" DependsOnTargets ="$(OnUnitTestFailureDependsOn)" />
<Target Name="BeforeUnitTestFail">
<Message Importance="high" Text="Unit Test failure in build - start" />
Target>
<Target Name="AfterUnitTestFail">
<Message Importance="high" Text="Unit Test failure in build - complete" />
Target>
DIV>
What this does is capture the error from the unit testing, and then create a work item when it happens. While I was at it I implemented the suggestion from Steve St. John's post and put in the attribute of Assigned To=Bruce Chapman, so that the generated work item is assigned to me if unit tests fail. (note that his post recommends using 'Chapman, Bruce' but it works firstname lastname for me.