Thursday, 15 May 2014

Team Foundation Server, Continuous Integration and separate projects for JavaScript unit tests

Do you like to separate out your unit tests from the project you are testing? I imagine so. My own practice when creating a new project in Visual Studio is to create a separate unit test project alongside whose responsibility is to house unit tests for that new project.

When I check in code for that project I expect the continuous integration build to kick off and, as part of that, the unit tests to be run. When it comes to running .NET tests then Team Foundation Server (and it's cloud counterpart Visual Studio Online) has your back. When it comes to running JavaScript tests then... not so much.

This post will set out:

  1. How to get JavaScript tests to run on TFS / VSO in a continuous integration scenario.
  2. How to achieve this *without* having to include your tests as part of web project.

To do this I will lean heavily (that's fancy language for "rip off entirely") on an excellent blog post by Mathew Aniyan which covers point #1. My contribution is point #2.

Points #1 and #2 in short order

First of all, install Chutzpah on TFS / VSO. You can do this by following Steps 1 - 6 from Mathew Aniyan's post. Instead of following steps 7 and 8 create a new unit test project in your solution.

Edit 29/05/2014: Matthew Manela (creator of Chutzpah) has confirmed that this is the correct approach - thanks chap!

To our unit test project add your JavaScript unit tests. These should be marked in Visual Studio with a Build Action of "Content" and a Copy to Output Directory of "Do not copy". You should be able to run these tests locally using the Visual Studio Chutzpah extension - or indeed in some other JavaScript test runner. Then, and this is the important part, edit the csproj file of your unit test project and add this Import Project statement:

  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />

Ordering is important in this case. It matters that this new statement sits after the other Import Project statements. So you should end up with a csproj file that looks in part like this: (comments added by me for clarity)

  <!-- Pre-existing Import Project statements start -->
  <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- Pre-existing Import Project statements end -->

  <!-- New addition start -->
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
  <!-- New addition end -->

Check in your amended csproj and the unit tests to TFS / VSO. You should see the JavaScript unit tests being run as part of the build.