in

TFS Advantage

Furthering Continuous Integration Efforts on Microsoft Visual Studio Team System Team Foundation Server

Tim Bassett

Some keys to success with continuous integration and VSTS

Third Party Software

All third party software should be treated as part of the source code.  It needs to be included in the VSTS source code repository using the same relative paths as would be expected on a developer’s machine.  The exception to this is binaries installed in the GAC (which  really is the developer’s enemy, not his friend, but that’s a subject for later).  Additionally, the only way to get the same results everywhere is to use the same version everywhere.  If the developers are using Acme.dll, version 1.2.3.4 on their machines, the version in source control needs to match.  All developers upgrade at the same time.  This will prevent late night tail chasing of a build or test failure.   To accomplish these goals, place all third party software into an appropriate folder in the “thirdparty” directory of any of your VSTS projects.  I typically will place the files there first, then go reference them from my projects.  Using this practice, you avoid the “prototyping” and forgetting to update a path before checking in.  After setting these references, remember to go into the Source Code Explorer and add them to the appropriate place(s).  Include them with your initial check-in of their usage. Most third party software does not require installation, nor registration on a build server to be successful. 

Unit Testing

Couple of items of note about writing unit tests.  Unit tests should be automatable, predictable and reproducible.  This means no UI elements popping up in them.  I rarely recommend modifying production code for testing infrastructure needs.  (e.g. exposing a property with a higher than originally intended scope, compiler directives, etc).  MSTest does have some great facilities to get to the innards of a production class without having to actual modifying the production code.  These are the private accessors;  I find these meet 99% of your needs for accessing private members, I chalk the other 1% up to, “oh well, that part won’t be tested as well.”  BTW, when I say not to modify production code to meet your testing infrastructure, I mean only that.  I modify production code daily to make it more testable, but that’s a completely different development activity.  

Single Directory Compilation

It takes a little more upfront work, but I recommend (especially for managed assemblies) to adopt a single output folder strategy.  (this might be trickier with unmanaged C++) I do this for a number of reasons:

  • Non referenced (or loosely coupled assemblies) will be available to other assemblies.  In other words, if I have a assembly I build and its pulled into the application at run time, but nothing references directly as a project, it will be there from the last compilation.  This negates a manual copy/paste operation, or monkeying with post build events in the projects.
  • It’s faster – quite simply, if you do this and set “Copy Local = false”, the compiler/operating system doesn’t have to copy and move all of your referenced assemblies around to keep the dependent assemblies up to date.  It builds it into the obj directory, puts a copy into the output, and that’s it.  In a larger solution of 100 projects with tons of references and a large dependency tree, compile times skyrocket.  This mitigates that problem.
  • You always know where your outputs are and can quickly see what is up to date and what’s not.
  • You can do a “hard clean” (Shift-Del) REAL easy.
  • Oh, and it’s the way the build server is going to build your software anyway, so when you look like the build server, the build server becomes your friend, not your enemy.  Some hinky problem that might come up in the build will more than likely produce itself on your box, before you check in. My trick to doing this is to prefix your <OutputPath> value in your project files with the $(SolutionDir)property (macro), and subsequently your project templates (located in a path similar to C:\Users\tim\Documents\Visual Studio 2008\Templates\ProjectTemplates ) to have the following.  This automagically puts into a single directory compilation strategy.  It does NOT set your CopyLocal = false.  

 

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 

<DebugSymbols>true</DebugSymbols>
<
DebugType>full</DebugType>
<
Optimize>false</Optimize>
<OutputPath>$(SolutionDir)\bin\Debug\</OutputPath>
<
DefineConstants>DEBUG;TRACE</DefineConstants>
<
ErrorReport>prompt</ErrorReport>
<
WarningLevel>4</WarningLevel>
</PropertyGroup>

 

Monitoring The Build

Monitor the build after submitting changes, monitor the status.  You can do this using several methods:
  • The build explorer is available from the Team Explorer right in VS.net. 
  • If you install the Team Foundation Server Power Tools (highly recommended), you can run the Build Notification tray app.
  • Project Alerts – will email you the results of every build.  I have an Outlook rule that moves the successful ones to a subfolder and leaves failed builds in my inbox.
On this note, it is pretty important that you come up with your guidelines on what to do when you have a broken build.  There are many blogs are how people handle them.  My practices (depending on the size of the development team) range from the casual to the tightly controlled.  In smaller groups, usually the developer who’s submission it was and figures it out and gets if fixed in a reasonable amount of time.  When working with large development teams with some reckless developers, I have helped them institute the 3/30 rule, “You get three attempts or 30 minutes.  If not fixed by then, roll it back and get out of the way.”  What is important is that you come up with your own procedures.

 

Comments

No Comments
Hound Dog Enterprises, LLC
Powered by Community Server (Non-Commercial Edition), by Telligent Systems