Showing posts with label NuGet. Show all posts
Showing posts with label NuGet. Show all posts

Monday, 11 May 2015

NuGet Package Restore and Unit Test filtering in TFS Build Online

In a previous post I blogged about how to set up a project so that the NuGet packages aren't added to source control. This post is a sort-of sequel to that one, looking at basic steps in getting the same project building in TFS Build and having its unit tests run by TFS Build. In my case I'm using TFS Build Online, but the steps should be pretty similar in an on premise installation of TFS Build.

We're aiming to end up with this:



This is what we do:

1. Create a new Build Definition using an appropriate build process file

New Build Definitions are created in Visual Studio 2013 in Team Explorer, Builds, click on the "New Build Definition" link.

You are shown a tabbed properties sheet. Most of the tabs are fairly self explanatory but the most complicated one is the "Process" tab. The "Build process file" which you select at the top, controls which "Build process parameters" you are shown at the bottom.

The key here is that we need to select a build process file that will restore NuGet packages before building as we are not checking our NuGet packages into TFS. The default build process file in my version of TFS is "DefaultTemplate.11.1.xaml"; this will not restore NuGet packages so it's no good for our purposes. In TFS Build Online there is a build process file called "TfvcTemplate.12.xaml" available which does restore NuGet packages before build, so I use this.

(In the end the build process file is simply a WF 4 workflow; if you want to you can customise it and even add WF activities that you have defined yourself)

2. Specify the solution(s) to build and unit test filters

This is where we set the Build process parameters:



In the "2.Build" section set the solutions to build as shown above.

Now, the test filters.  You may not want to use test filters of course, you may want to run all your unit tests. In my case I have an Azure Cloud Services application that uses Azure table storage for most of the backing storage. I therefore have (roughly) three kinds of unit tests:

  1. Tests that test the repository layer and therefore need a running Azure Storage Emulator to work.
  2. Tests that have some kind of dependency upon the environment being configured in a certain way (in production this is achieved by using Cloud Services Startup tasks).
  3. Tests that use a mock implementation for the repository layer and do not have any dependency on the environment other than using file system directories available through the TestContext object.

Tests of types (1) and (2) will always fail if run by TFS Build; how do I tell TFS Build that I only want to run tests of type (3)?  Answer: using the Test case filter property in my build process parameters (if you're using a different build process file the property may be called something different, but it will almost certainly be there somewhere). I indicate the tests that are of type (1) or (2) by decorating them with TestCategory attributes, as shown below:


        [TestMethod, TestCategory("RequiresStorage")]
        public void CreateAndRetrieveUser()

I give tests of type (1) a TestCategory of "RequiresStorage" and tests of type (2) a TestCategory of "RequiresInfrastructure". Then I set the Test case filter to:


TestCategory!=RequiresStorage&TestCategory!=RequiresInfrastructure

as shown above.  That's all!

Tuesday, 5 May 2015

Keeping NuGet packages out of TFS

When you start working with Visual Studio 2013 and TFS, by default Visual Studio adds your NuGet packages to TFS Source Control. This works OK but it's a bit backward; the whole point of having NuGet is that it acts as the repository for these packages so your source control system doesn't have to. And for one of my projects packages\ now contains 163 MB which is a lot of lard for source control to handle. So I decided to try and find out how to exclude the packages from TFS and keep them out.

I've read a few posts on how to do this:
So this is a step-by-step process of how to create a new solution and have (almost) all the packages kept out of TFS.

1. Create a .tfignore file

In the TFS folder that is the parent folder of all my projects I create a ".tfignore" file containing the following:


1
2
3
4
5
*.user
*.suo
bin
obj
packages

This instructs TFS to ignore any folder called "packages". Add the file to source control so that all your projects on all your dev machines get the benefit of this.

You would have thought that that is it, but it's not...

2. Create my new project by initially creating an empty solution file

The option to create a Blank Solution is in the "Other Project Types" section:


Close Visual Studio (if you don't do this, it won't work).

3. Add a "nuget.config" in a ".nuget" folder within the new solution

Create a ".nuget" folder within the solution folder and add a "nuget.config" file to it that contains the following:


1
2
3
4
5
<configuration>
    <solution>
        <add key="disableSourceControlIntegration" value="true" />
    </solution>
</configuration>

This is needed to stop NuGet.exe from trying to add packages to source control (it ignores the .tfignore file, a known issue). We want to do this before we add any projects so that NuGet uses our new settings for the packages in the initial project.

4. NOW add your projects to the solution...

In my case I added an MVC project and a Tests project.  I'm hoping that in the Pending Changes window I should see NOTHING being added from the "packages" folder even though my MVC project uses loads of packages.

And this is what I see:


Almost nothing. I can't seem to stop nuget / TFS (whichever one it is that is doing it) from adding the repositories.config to source control.  Fortunately this file is only about 200 bytes as opposed to the 163 MB I was putting in source control before.

If you use Git rather than TFS for source control then the only difference to this process would be that you would need to create a ".gitignore" instead of a ".tfignore" file.