Continuous Integration: From Theory to Practice 2nd Edition

Published 15 January 08 05:10 AM | cjlotz

image During last year I created a guide on implementing Continuous Integration (CI) for a .NET 2.0 development environment.  The guide illustrates how to create a complete CI setup using VS 2005 and MSBuild (no NAnt) together with tools like FxCop, NCover, TypeMock, NUnit, Subversion, InstallShield, QTP, NDepend, Sandcastle and CruiseControl.NET.

The good news is that I spend some time during the last 2 weeks greatly improving the setup for use on a new VS 2008 project and I have decided to release a 2nd Edition of the guide covering the much improved setup smile_shades  Instead of creating another series of blog posts to cover the content, I'm releasing the 2nd edition only as a downloadable PDF guide together with all the associated code and build artifacts.  This will allow new teams to get up and running with CI a lot quicker.

For readers of the first edition of the guide, the most notable differences between the second edition and the first edition of the guide are:

  1. Updated to use VS 2008, .NET 3.5 and MSBuild 3.5 (including new MSBuild features like parallel builds and multi-targeting).
  2. All tools (NUnit, NDepend, NCover etc.) are now stored in a separate Tools folder and kept under source control. The only development tools a developer needs to install are VS 2008, SQL Server 2005 and Subversion. The rest of the tools are retrieved form the mainline along with the latest version of the source code.
  3. Added the CruiseControl.NET configuration (custom style sheets, server setup etc.) to source control and created a single step setup process for the build server. This greatly simplifies the process of setting up a new build server.
  4. Changed from using InstallShield to Windows Installer XML (WiX) for creating a Windows installer (msi).
  5. Added support for running MbUnit tests in addition to the NUnit tests.
  6. Added support for running standalone FxCop in addition to running VS 2008 Managed Code Analysis.
  7. Added targets to test the install and uninstall of the Windows installer created.
  8. Consolidated the CodeDocumentationBuild to become part of the DeploymentBuild.
  9. Removed the QTP integration as this was not a requirement for the new project. If you want to integrate QTP, please refer to the QtpBuild of the first edition of the guide.
  10. Used the latest version of all the tools available.  The tools used in the guide are VS 2008, Subversion, CruiseControl.NET, MSBuild, MSBuild.Community.Tasks, NUnit/MbUnit, FxCop, TypeMock/Rhino.Mocks, WiX, Sandcastle, NCover, NCoverExplorer and NDepend.

I hope you find it to be a useful resource for assisting you with creating your own CI process by harnessing the power of MSBuild!  If you have any questions, additional remarks or any suggestions, feel free to drop me a comment.

Download

Here are the links:

  1. PDF Guide
  2. Code and Build artifacts 

Change History

  • 15/01/2008 - Initial publication
  • 07/04/2008 - Fixed a problem with the CodeCoverage target when using MbUnit that was not passing the assemblies to profile via the command line

Comments

# si said on January 15, 2008 06:10 AM:

Sweet, thanks again for sharing!

Funny thing is we were already doing points 2. and 3. in your list of differences :)

Only exception is in 3. we have a pre-build task to ensure appropriate directories used by CC.NET and MSBuild have been created.

# Mladen said on January 15, 2008 06:21 AM:

You should also try out Team City - great software and much easier to set up than Cruise Control.

www.jetbrains.com/teamcity

# Rob said on January 15, 2008 06:09 PM:

CruiseControl is not that hard...  NAnt, on the other hand, is a bit more complicated, but also not that hard once you've done it a couple times.  Plus I've found that writing a build script helps me better understand what I need to do to deploy.

# cjlotz said on January 15, 2008 07:49 PM:

I agree with Rob, learning CruiseControl .NET is not that hard.  I had a look at TeamCity 3.0 a while back but found it difficult to configure and the support for plugging in different tools (test frameworks etc.) IMO is still lacking.

I'm quite happy with using CC.NET and MSBuild.  I use NAnt only for .NET 1.1 and earlier setups.

# Trumpi's blog said on January 15, 2008 09:10 PM:

I'm quietly spending my last week of leave at home... Agile and Project Management Why do Some Projects

# Reflective Perspective - Chris Alcock » The Morning Brew #11 said on January 16, 2008 08:14 AM:

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #11

# 2 Links Today (2008-01-16) said on January 16, 2008 03:18 PM:

Pingback from  2 Links Today (2008-01-16)

# Paul said on February 19, 2008 03:48 PM:

This is great, thanks!  I do have a couple of questions though.

First, Should you be able to do this build without VS. Just using MSBuild and the .Net SDK?

Second, unfortunately, we are not moving to 2008 yet, so, I would like to be able to use the new setup with the tools in Subversion, how hard is it to convert this to use 2005?

# cjlotz said on February 20, 2008 03:21 PM:

Hi Paul

Glad you enjoyed it.  To answer your questions:

1. The only reason for installing VS on the build server is to support managed code analysis (ie. the code analysis done in the IDE).  You can run the standalone version of FxCop (I include a Target for this in the guide), but unfortunately the results are not quite the same as for managed code analysis as it doesn't take your Suppressions into account that you added to the code.

2. You should be able to use the improved setup as is for VS 2005 except for the MSBuild 3.5 features that I utilize.  This includes:

- Multi-targeting via /tv: and /p:TargetFrameworkversion MSBuild parameters

- Parallel builds via the /m: and BuildInParallel=true MSBuild parameters

- Ability to define dynamic ItemGroups and PropertyGroups within Targets.  You will have to use the CreateItem and CreateProperty tasks for .NET 2.0

Hope this helps :-)

Carel

# Sean said on April 7, 2008 03:34 PM:

There appears to be a bug with the NCover/MbUnit execution in the "CodeCoverage" target.  The commandline for MbUnit is missing the Test Assembly to execute.

Change this section:

     <!-- Using MbUnit -->

     <NCover

         ToolPath="$(NCoverPath)"

         CommandLineExe="$(MbUnitCmd)"

         CommandLineArgs="$(MbUnitReportFormat)  /verbose /report-name-format:%(TestAssemblies.Filename)%(TestAssemblies.Extension).$(TestResultFile) /report-folder:$(DOUBLE_QUOTES)%(TestAssemblies.RootDir)%(TestAssemblies.Directory)"

         CoverageFile="%(TestAssemblies.FullPath).$(NCoverResultFile)"

         LogLevel="Normal"

         LogFile="%(TestAssemblies.FullPath).$(NCoverLogFile)"

         WorkingDirectory="%(TestAssemblies.RootDir)%(TestAssemblies.Directory)"

         ExcludeAttributes="CoverageExcludeAttribute"

         Assemblies="@(CodeAssemblies)"

         RegisterProfiler="false"

         ContinueOnError="true"/>

To this:

     <!-- Using MbUnit -->

     <NCover

         ToolPath="$(NCoverPath)"

         CommandLineExe="$(MbUnitCmd)"

         CommandLineArgs="$(MbUnitReportFormat) %(TestAssemblies.Filename)%(TestAssemblies.Extension) /verbose /report-name-format:%(TestAssemblies.Filename)%(TestAssemblies.Extension).$(TestResultFile) /report-folder:$(DOUBLE_QUOTES)%(TestAssemblies.RootDir)%(TestAssemblies.Directory)"

         CoverageFile="%(TestAssemblies.FullPath).$(NCoverResultFile)"

         LogLevel="Normal"

         LogFile="%(TestAssemblies.FullPath).$(NCoverLogFile)"

         WorkingDirectory="%(TestAssemblies.RootDir)%(TestAssemblies.Directory)"

         ExcludeAttributes="CoverageExcludeAttribute"

         Assemblies="@(CodeAssemblies)"

         RegisterProfiler="false"

         ContinueOnError="true"/>

# cjlotz said on April 8, 2008 06:33 AM:

Thanks for pointing it out, Sean.  I have fixed it and uploaded new versions of the guide and build files

Carel

# From the software development trenches said on May 12, 2008 09:24 AM:

I&#39;ve said it before and I want to say it again. If you are serious about code quality and you want

# From the software development trenches said on July 8, 2008 03:13 PM:

As the blog post says, I haven&#39;t been too active on the blogging front for the past 2-3 months.&#160;

# Code Metrics - From the software development trenches said on July 12, 2008 08:28 AM:

Pingback from  Code Metrics - From the software development trenches

# si said on July 30, 2008 03:47 AM:

Hi again, one thing I just implemented which you may be interested in is merging our NUnit and NCover targets so unit tests are only executed once instead of twice.

Since NCover invokes NUnit (or whatever), I just added the option to output xml results for each test assembly, and then CruiseControl.NET picks up both NCover and NUnit results for merging.

So our MSBuild NCover task CommandLineArgs attribute is now:

CommandLineArgs="$(DOUBLE_QUOTES)%(TestAssemblies.FullPath)$(DOUBLE_QUOTES) /nologo /xml=$(DOUBLE_QUOTES)$(CIArtifactDirectory)\nunit-result-%(TestAssemblies.Filename).xml$(DOUBLE_QUOTES)"

The only caveat to this may be if you record test times, as I'm guessing NCover may slightly influence the execution time.  However, that shouldn't be a problem if you always do this, only in moving from one approach to the other.

What do think?

# From the software development trenches said on August 1, 2008 07:19 AM:

It seems like I spend a lot of time on this blog talking about Continuous Integration &#160; Well, in

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: