Part 1: Continuous Integration using MSBuild, CruiseControl.NET, FxCop, NUnit, NCover + Subversion

Published 04 April 07 08:03 PM | cjlotz

imageI've spend the last week or so refactoring our Continuous Integration (CI) process at work.  Our current build was causing quite a few headaches - from not showing the build stats correctly to being too slow etc.  I decided to redo the whole CI process and thought I'd document the process as a series of blog posts to serve as a guide for creating a CI process using MSBuild, VS 2005, InstallShield, NCover, NDepend and Mercury Quick Test Professional together with open source tools like CruiseControl.NET, FxCop, NUnit, Sandcastle and Subversion. 

The series consists out of the following posts:

  • Part 1 covers the background, requirements, process and tools required for the whole CI process.  
  • Part 2 covers the common build targets and tasks that are used by the DeveloperBuild, DeploymentBuild, CodeStatisticsBuild, CodeDocumentationBuild and QtpBuild
  • Part 3 covers the DeveloperBuild
  • Part 4 covers the DeploymentBuild
  • Part 5 covers the CodeStatisticsBuild
  • Part 6 covers the CodeDocumentationBuild
  • Part 7 covers the QtpBuild

Lastly I end off the series by showing you how to use some additional community extensions to add some further panache to your CI build. 

You can also find a complete, downloadable pdf booklet of the series here smile_shades.

Change History

  • 12/12/2007: Added the GetEnvironment target to InitialTargets; Changed environment specific builds of DeploymentBuild to also depend upon the Environment.txt file.
  • 11/12/2007: Changed the CodeStatisticsBuild to run NDepend as part of the build; Consolidated all the targets into a single build file; Updated the CC.NET configuration to make use of new build queue features available in CC.NET 1.3 and removed duplication from the CC.NET configuration through using DTD entity references.
  • 28/09/2007: Changed the QtpBuild to make use of incremental builds to install/uninstall the application and to run the test cases, identified in a file, from within Mercury Quality Center.
  • 17/09/2007: Added the QtpBuild and updated the series to include links to the new content.
  • 31/08/2007: Added the link to the downloadable booklet for the complete series.
  • 17/08/2007: Updated content to include the CodeDocumentationBuild and the link to the CCStatistics post.
  • 25/04/2007: Fixed broken CruiseControl.NET link.

Resources

I found the following resources helpful for getting to grips with the power of MSBuild:

  1. Book: Deploying .NET Applications: Learning MSBuild and ClickOnce
  2. Channel 9 Wiki: MSBuild.Links
  3. Channel 9 Wiki: MSBuild.HomePage
  4. MSDN Library: MSBuild Overview
  5. MSDN Library: MSBuild Reference
  6. Code: MSBuild Community Tasks
The documentation for CruiseControl.NET was sufficient for setting up the build server to use CC.NET with MSBuild.

Background

Before delving into the CI process itself, I need to provide some background on our application to create the context for our CI process.  The application, developed using VS 2005, is a stand-alone WinForms application with integration points to various other systems/applications via web services/third party API's.  We use Subversion for source control and some third party libraries/controls from vendors like Infragistics, Xpo. We have tried to develop the application using Agile practices like TDD and we are currently running on 1 week iterations. At the end of each iteration we produce a build (.msi) that is released to our testers.  We treat all our databases as just-another-code-artifact and have scripts that allow us to create the databases' structure and content.  We are able to at any point in time setup a new development environment by simple getting the latest version from our repository. 

To facilitate all of this, we have standardized on using the following directory structure for our solution:

 image

  • Builds folder contains a separate folder for every build and its build artefacts.
  • Code folder contains all our VS 2005 projects as a flat hierarchy of sub-folders.  All the .sln files reside in the Code root folder.  We have a Code\Deploy sub-folder to which all the non-unit test project outputs are compiled.
  • Code Metrics folder contains all the metrics that we generate for our system like the code coverage results.
  • Documentation folder contains the help file settings and MSDN style help file we generate from our XML code comments.
  • Install folder contains our InstallShield .ism file and various merge modules and other files required to create a .msi install for our system.
  • Lib folder contains all the third party libraries (Infragistics, NUnit, TypeMock, XPO etc.) that are used as project references.
  • Qtp folder contains the RunQTP.vbs script file and a TestCases sub-folder that contains a list of test suite files.  Each test suite file contains a list of individual Qtp test cases to run.
  • Sql folder contains a sub-folder for every database that we use.  Each database sub-folder contains all the .sql script files to create the structure and content for the database as well as batch files to automate this creation process using osql/sqlcmd.  We support both sql 2000 + sql 2005.

Process

One of the requirements for our CI process is that a developer should be able harvest the same process as the build server to work in his/her sandbox/private workspace before committing their changes to the repository.  The build server will obviously use a few additional tasks for deployment, but the same compile/test process should be re-usable from within both the developer sandbox/private workspace and build server.

Our build needs to do the following tasks:

  1. Get the latest source from the repository
  2. Build the databases
  3. Compile the source
  4. Run the unit tests
  5. Produce code coverage results
  6. Produce FxCop results
  7. Produce NDepend results
  8. Build MSDN style help documentation
  9. Backup the databases
  10. Version the source code
  11. Build a msi
  12. Deploy the msi
  13. Run the regression test pack using QTP
  14. Notify QTP testers via e-mail
  15. Tag the repository

Not all of these tasks need to be completed on a continuous basis.  Some (like steps 9-15) are only required to run once weekly as part of the iteration build to create the .msi.  We also found that creating MSDN style documentation as well as running code coverage and code analysis on every check-in caused our solution build, that currently consists out of 83 projects, to take way too long. We therefore decided to create a staged build/build pipeline and to split our CI build process into 5 separate builds on two separate servers.

  1. DeveloperBuild (Runs on BuildServer) - This build is set to monitor the repository every 60 seconds for changes.  It builds the databases, compiles the source code and runs the unit tests.  It does incremental builds for building the databases, compiling the source code and for running the tests to get quicker build times. 
  2. DeploymentBuild (Runs on BuildServer) - The deployment build is run once weekly at 12:30 on Friday afternoons to create the .msi installation that is deployed to our QTP testers.  In addition to creating and deploying the .msi it also tags the repository to create a tag for the work done for the iteration.
  3. CodeStatisticsBuild (Runs on BuildServer) - The statistics build is set to run on successful completion of the deployment build and produces the Code Coverage, FxCop and NDepend results for the week.  The developers can still evaluate the code coverage, FxCop and NDepend results continuously in their sandbox, but we incur the overhead of this on the build server only once a week.  This way we can have the stats to spot trends on a weekly basis.
  4. CodeDocumentationBuild (Runs on BuildServer) - The documentation build is set to be invoked manually and creates MSDN style help documentation from the XML code comments.
  5. QtpBuild (Runs on QtpServer) -  The QtpBuild runs on a dedicated machine as the regression test pack takes quite some time to run through (3 hours in our scenario).  The build triggers on the completion of a successful DeploymentBuild on the normal build server.

As evident, the first server (aka the BuildServer) will do all builds except for the QtpBuild. The second server (aka the QtpServer) will only run the regression test pack using QTP.

Build Server Tools

These are the tools that are used by our CI process and that needs to be installed on our build server running Windows Server 2003:

  1. Visual Studio 2005 Team Edition for Software Developers to run Managed Code Analysis (aarrgghhhh!).  You can use the standalone version of FxCop, but there are some differences between this and the version used for VS 2005 Code Analysis.  Unfortunately you therefore need to install the complete VS 2005 Team Edition for Software Developers.
  2. NCover v1.5.8 for Code coverage.
  3. NCoverExplorer v1.4.0.7  and NCoverExplorer.Extras v1.4.0.5 to create Code coverage reports.
  4. NDepend v2.6 for additional code metrics.
  5. MSBuild.Community.Tasks for some additional MSBuild tasks.
  6. NUnit 2.0 2.4.5 to run the unit tests.
  7. .NET Framework 2.0
  8. .NET Framework SDK 2.0
  9. CruiseControl .NET 1.3
  10. InstallShield Standalone Build v12 - The standalone build is the InstallShield build engine without the GUI and you are allowed to install this on a build server for free granted you have a valid InstallShield license.
  11. Subversion 1.4.5 for source control.
  12. HTML Help Workshop for building HTML help 1.x files.
  13. Visual Studio .NET Help Integration Kit 2003 for building help files that can integrate into Visual Studio.
  14. Sandcastle June 2007 CTP to generate the help file content from the XML code comments.
  15. Sandcastle Help File Builder (SHFB) to set the options for the help file and to bootstrap the document creation process.
  16. Sandcastle Presentation File Patches to solve some issues with the Sandcastle June CTP.  Extract the contents of the ZIP archive to the Sandcastle installation directory.
  17. Mercury QuickTest Professional 8.2 for automated regression testing.

Next Steps

Well, that takes care of the all the background information.  The next post will delve into all the common build targets that are used by the DeveloperBuild, DeploymentBuild, CodeStatisticsBuild, CodeDocumentationBuild and QtpBuild. Keep watching this space... smile_regular

B.t.w, I'm a big fan of ReSharper and the MsBuild/NAnt support of ReSharper is oh so sweet!!

Comments

# Eric Bowen's .NET Technology Blog said on April 4, 2007 10:05 PM:

Here is a great sample CruiseControl.NET config with Subversion and MSBuild:http://dotnet.org.za/cjlotz/archive/2007/04/04/part-1-continuous-integration-using-msbuild-cruisecontrol-net-fxcop-nunit-ncover-subversion.asp...

# Thea Burger said on April 9, 2007 08:11 PM:

I've been putting off installing ReSharper because I'm worried about the performance of my machine, but I'm feeling the pressure more and more... :)

Your setup sounds a lot like ours (just more detailed!), and I want to improve ours soon as well (e.g. don't have NCover integrated at the moment), so I'll check back on your posts - excellent posts, thanks! Something I battled with: CruiseControl + MsBuild + NUnit + multiple assemblies (http://dotnet.org.za/thea/archive/2006/07/26/CruiseControl-_2B00_-MsBuild-_2B00_-NUnit-_2B00_-multiple-assemblies.aspx)

# Andrew Stevenson's WebLog said on April 10, 2007 03:00 PM:

Part 1: Continuous Integration using MSBuild, CruiseControl.NET, FxCop, NUnit, NCover + Subversion: http://dotnet.org.za/cjlotz/archive/2007/04/04/part-1-continuous-integration-using-msbuild-cruisecontrol-net-fxcop-nunit-ncover-subversion.aspx

# Hemant Sathe said on April 24, 2007 07:45 AM:

Carel,

The cruise control link is broken. Thanks a lot for a great series on this topic.

Regards,

Hemant.

P.S. Congrats on becoming father of a cute baby boy.

# cjlotz said on April 25, 2007 08:11 AM:

Hemant,

Thanks :-)  Trust you are doing well.  I'll fix the link ASAP.  Keep well...

# qgyen.net | blog of ken robertson said on May 9, 2007 10:11 PM:

As a follow up on my post yesterday about continuous integration, I am really starting to like MSBuild

# qgyen.net | blog of ken robertson said on May 11, 2007 07:33 AM:

I've really been getting up to speed on using MSBuild and think I have a very nice base set of build

# Marcel du Preez said on August 3, 2007 02:47 PM:

Hi Carel,

Sit hier in London en is besig om Buildserver te bou... raai op wie se article kom ek toe af!

Hoop alles gaan goed daar!

Marcel

# Part 2: Continuous Integration using MSBuild - The Common Build targets - From the software development trenches said on November 7, 2007 09:59 AM:

Pingback from  Part 2: Continuous Integration using MSBuild - The Common Build targets - From the software development trenches

# Continuous Integration For .NET 2.0 Development Environments: Downloadable Booklet - From the software development trenches said on November 7, 2007 10:59 AM:

Pingback from  Continuous Integration For .NET 2.0 Development Environments: Downloadable Booklet - From the software development trenches

# From the software development trenches said on November 8, 2007 04:06 PM:

Performance is a very critical non-functional requirement for the SmartClient application that we are

# From the software development trenches said on November 23, 2007 10:22 AM:

In previous posts about Code Metrics and Code Reviews , I explored some metrics and techniques that I

# From the software development trenches said on December 3, 2007 08:08 PM:

Continuous Integration (CI) is a popular incremental integration process whereby each change made to

# Part 3: Continuous Integration - The DeveloperBuild - From the software development trenches said on December 11, 2007 10:39 PM:

Pingback from  Part 3: Continuous Integration - The DeveloperBuild - From the software development trenches

# Part 4: Continuous Integration - The DeploymentBuild - From the software development trenches said on December 11, 2007 10:40 PM:

Pingback from  Part 4: Continuous Integration - The DeploymentBuild - From the software development trenches

# Part 5: Continuous Integration - The CodeStatisticsBuild - From the software development trenches said on December 11, 2007 10:41 PM:

Pingback from  Part 5: Continuous Integration - The CodeStatisticsBuild - From the software development trenches

# Part 6: Continuous Integration - The CodeDocumentationBuild using Sandcastle - From the software development trenches said on December 11, 2007 10:41 PM:

Pingback from  Part 6: Continuous Integration - The CodeDocumentationBuild using Sandcastle - From the software development trenches

# Part 7: Continuous Integration - The QtpBuild - From the software development trenches said on December 11, 2007 10:42 PM:

Pingback from  Part 7: Continuous Integration - The QtpBuild - From the software development trenches

# Jay Flowers said on January 27, 2008 11:11 PM:

This is a great series!

If you want something like this without having to write it yourself take a look at CI Factory:

http://www.cifactory.com

# Derek Smyth said on March 7, 2008 09:52 AM:

this was exactly what I needed !!!

many many thanks for posting this information.

# CodeObsessed said on March 27, 2008 08:50 AM:

Found these don't want to forget them :) blogs.conchango.com/.../Setup-of-our-continuous-integration-build.aspx

# From the software development trenches said on July 17, 2008 10:52 AM:

I've been considering the best way to version our .NET assemblies to support the roll-out of automatic

# Glenn Wilson said on July 21, 2008 03:20 PM:

If you place the build file (.proj) into the root of the project folder, you specify the SolutionLocation to locate the Solution file.  The solution file provides us with information about the location of the project files (obtained from the GetSolutionProjects node). In particular, the project files are derived from the relative path from the solution file.  Therefore, the CSProjects value contains only relative paths, not absolute paths.  So, the "src" folder is not included in the path.  However, relative to the position of the build file, the project files require the "src" file to be explicitly defined in the CSProjects item group.  I guess that this is unique to VS2008 and does not affect VS2005 since the older version of the IDE created references to folders within the ide environment, but the new IDE doesn't?

# 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   Well, in

# AlSki.net said on August 14, 2008 11:36 PM:

CruiseControl Setup

Leave a Comment

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

Enter the numbers above: