RSS Feed

Getting Started with Continuous Integration

Posted on Wednesday, April 1, 2009 in MAXoutput

by Sondre Bjellås

sondre-bjellas Continuous Integration is a development practice that can help improve your company’s ability to deliver quality software. It can reduce the time to market and the deployment cycle from functional complete products to having the solutions deployed on desktop or servers.

Continuous Integration, or CI, can start with a lone developer desktop and mature closer towards production. The ultimate goal is to have a CI environment that can take you from checked-in code to production ready installation packages.

The instructions in this article will help you get started with CI even if you’re a single developer or a small team.

This is a process that takes time, but don’t be afraid of the road ahead, I will walk you through the first baby-steps towards a well-tuned machine. CI-practice is one of many important elements for the software development industry to mature to levels of other types of manufacturing.

Introduction to Continuous Integration

Martin Fowler has written a very good introduction to CI which you can read this on his website: http://martinfowler.com/articles/continuousIntegration.html [1]

Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily – leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. This article is a quick overview of Continuous Integration summarizing the technique and its current usage.

The clean and simple essence of CI is to avoid the situation “It works on my machine”. This has caused a lot of pain between developer and users, but also between developers. Most of us have experienced that our projects stops compiling properly after a Get Latest operation on the source control system. Another important aspect of CI is to have a cycles of automatic compilation and testing of your projects. We will get deeper into automatic testing later in this article.

Source Control Systems

If you are not familiar with source control systems (SCM), I suggest reading a good introduction by Eric Sink. While the first CI example I will give in this article doesn’t use SCM, it is an essential piece of the puzzle if you’re doing computer software development. Even as a single developer, it’s advisable to use a SCM. SCM will give you better control and management of your projects, with history and the ability to restore deleted code.

Introduction to SCM: http://www.ericsink.com/scm/scm_intro.html [2]

There are many providers of SCM software; for the purpose of this article we will use Microsoft Visual SourceSafe. When your team grows and you have the finances to purchase licenses, I suggest upgrading to Microsoft Visual Studio Team System, which is a complete Application Life-Cycle Management (ALM) suite.

Setting up your environment

There are various CI solutions available for .NET developers, one of the most popular is Cruise Control .NET ( [3]).

[Please note that all examples are from a 64-bit system where the Program Files paths includes (x86) for 32-bit applications. If you have a 32-bit environment, please make sure you remove any reference to (x86).]

Cruice Control .NET (CC.NET) comes in various forms, for beginners the setup alternative is the simplest to get you started (CruiseControl.NET-1.4.2-Setup.exe).

clip_image002

clip_image004

After the installation has completed, a new folder will appear in the Windows start menu. From here we can access the main configuration file and launch the console application.

clip_image006

clip_image008

Before we continue with updates to our configuration file, we need to learn a little bit about build tools…

Build Tools

To compile the source code, you will need a tool that does the build for you. One alternative is NAnt, which is a free tool (http://nant.sourceforge.net/ [4]).

With Visual Studio 2005 Microsoft introduced MSBuild, which is a standalone build engine for .NET. This has made it more accessible for third parties and made it simpler to automate and script.

The simplest way to get started with a build process is to utilize MSBuild, which is already installed if you have .NET Framework 2.0. We will configure CC.NET to start the MSBuild process which takes care of the compilation of our Visual Studio Solution.

New Project or Existing Solutions

It is much less effort to include guidance, frameworks, and tools in the beginning of a new project. This applies to CI as well. The further you get in the development process, the harder it gets to make everything work properly in a CI-environment.

Sample Projects

For the purpose of this article, we’ll create a new Visual Studio solution called IntegrationSample. Within this solution we will create 3 projects: IntegrationSample (Windows Forms), Integration.Common (Class Library) and Integration.Test (Class library).

Add a Person.cs class to the Common project with the following code:

namespace Integration.Common
{
  public class Person
  {
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public DateTime Birthdate { get; set; }

    public bool IsOlderThan60()
    {
      return (Birthdate < DateTime.Now.AddYears(-60));
    }

    public override string ToString()
    {
      return string.Format("{0} {1}", Firstname, Lastname);
    }
  }
}

This class represents part of our business domain model and has certain business logic applied to it that is important to our business, namely the method that tells us if a person is more than 60 years old. The next step is to apply a test for our domain object.

Automated Testing with Unit Tests

Being able to automate the testing process of your projects is an important feature of a CI-environment. Having source code that works as tests for your application logic will help you when you’re later going back to modify, extend and fix existing code. With good tests you can ensure that your code changes won’t break the whole application. There are different frameworks available for unit testing, the most widely used with .NET is NUnit (www.nunit.org [5]). To learn more about test-driven development, visit Wikipedia: http://en.wikipedia.org/wiki/Test-driven_development [6]

clip_image010

clip_image012

When the installation of NUnit is complete, you can explore the included samples to learn more about writing unit tests. You can use the NUnit GUI to run your unit tests outside of the CI-environment.

clip_image014

To start writing unit tests, you need to add a reference to the following assembly in your Integration.Test project: "C:\Program Files (x86)\NUnit 2.4.8\bin\nunit.framework.dll". Additionally you should create a reference between the Test and the Common project, so we can access our business domain model in the tests project.

When you’re done adding the reference, let’s create a class named PersonTest.cs which will contain all the unit tests for our specific domain object.

using System;
using NUnit.Framework;
using Integration.Common;

namespace Integration.Test
{
  [TestFixture]
  public class PersonTest
  {
    [Test]
    public void IsOlderThan60Test()
    {
      Person person = new Person();
      person.Firstname = "Sondre";
      person.Lastname = "Bjellås";
      person.Birthdate = new DateTime(1905, 4, 4);
      Assert.IsTrue(person.IsOlderThan60());

      person.Birthdate = DateTime.Now;
      Assert.IsFalse(person.IsOlderThan60());

      person.Birthdate = DateTime.MaxValue;
      Assert.IsFalse(person.IsOlderThan60());
    }

    [Test]
    public void ToStringTest()
    {
      Person person = new Person();
      person.Firstname = "Sondre";
      person.Lastname = "Bjellås";
      Assert.AreEqual(person.ToString(), "Sondre Bjellås");
    }
  }
}

Tests are done through assertions. There are many types of assert methods included in the NUnit framework and you should use them to validate your business logic. Writing good unit tests is hard and it’s a practice in which you will continually improve as you get more experienced with it.

You can now begin to run and validate the unit tests on your local machine, open the NUnit GUI application and open the Integration.Test.dll file.

clip_image016

As you can see in my screenshot, both of the tests for the Person object validates. When we later go back to change the business logic, we can use the unit tests as a means to validate that our changes doesn’t break anything.

Bringing it all together

Let’s go back to the CC.NET configuration file and start modifying it so we get our CI-environment up and running. It’s advisable to have a dedicate computer that act as a build-computer, but it’s not a requirement.

The first thing we’re going to do is modify the default configuration file to run NUnit and our tests, here is the script so far:

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
 <project name="IntegrationSample">
  <tasks>
   <nunit>
    <path>C:\Program Files (x86)\NUnit 2.4.8\bin\nunit-console.exe</path>
    <assemblies>
     <assembly>C:\Source\Samples\IntegrationSample\Integration.Test\bin\Debug\Integration.Test.dll</assembly>
    </assemblies>
   </nunit>
  </tasks>
 </project>
</cruisecontrol>

Save the configuration and start the CruiceControl.NET application in the start menu. This will open a console application that will run your configuration. This is useful for beginners and when you’re setting up a new environment. When the configuration is complete, you should use the Windows Service for a more stable runtime.

clip_image018

When you ran the CC.NET installation, it should have created a virtual directory for you on the local Internet Information Services. If you happen to have any problems with this, make sure you create a virtual directory called webdashboard and map it to C:\Program Files (x86)\CruiseControl.NET\webdashboard.

Opening up the web dashboard should show us our IntegrationSample project and hopefully a green status, indicating that our unit tests has completed successfully. With the current configuration, we need to click the Force button to run tests.

clip_image020

This dashboard will be your viewport into the status and history of integration builds. You can drill down into the details of a build and you can have multiple CC.NET projects specified in the configuration file.

Our next step is to make CC.NET compile our source code using MSBuild.exe.

Within the element in the configuration, add the following script above the NAnt task, which will tell CC.NET to execute MSBuild.exe with our Visual Studio solution file.

<msbuild>
 <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
 <workingDirectory>C:\Source\Samples\IntegrationSample\</workingDirectory>
 <projectFile>IntegrationSample.sln</projectFile>
 <buildArgs>/noconsolelogger /p:Configuration=Debug /v:m</buildArgs>
 <targets>Build</targets>
 <timeout>720</timeout>
 <logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>

To validate that CC.NET is working correctly, we can go ahead and make a quick modification to the source code. If you reverse the operator for the age method, we should see the IntegrationSample fail on the dashboard. Drilling down into the details, we should see that our unit test fails.

clip_image022

The last and final step is to add support for a source control system. As you have now seen, you can setup an CI-environment without source control, but it makes sense to use source control. A source control system adds history and backup support and the ability to make heavy and local changes and not disrupt the active codebase which is inside the source control database.

Visual SourceSafe 2005

If you don’t have a source control system yet, an easy way to get started is with Microsoft Visual SourceSafe 2005. With an MSDN Subscription, you can download it from the downloads page.

clip_image024

When you go beyond a small team of programmers I suggest upgrading the source control with a more modern provider, like Visual Studio Team System or SourceGear [7].

Going back to Visual Studio and our IntegrationSample project, we will go ahead and add it to our source control provider of choice.

clip_image026

clip_image028

When the solution and all the projects is added to the source control, we can open the Visual SourceSafe Explorer and see how our newly added project is added and we can begin to check-out and check-in code changes.

clip_image030

We’re now ready for the final changes to our ccnet.config file. Open up the configuration file from the start menu and add the following new elements to the top beneath the element.

<triggers>
 <intervalTrigger seconds="60" />
</triggers>

 <sourcecontrol type="vss" autoGetSource="true" applyLabel="true">
 <executable>C:\Program Files (x86)\Microsoft Visual SourceSafe\ss.exe</executable>
 <project>$/IntegrationSample</project>
 <username>build</username>
 <password>Password123</password>
 <ssdir>C:\Source\VSS</ssdir> <!-- Path to your SourceSafe database -->
 <workingDirectory>C:\Source\Samples\IntegrationSample\Build\</workingDirectory>
 <cleanCopy>false</cleanCopy>
</sourcecontrol>

Make sure you use a different working directory than your normal project folder, if you are running CC.NET on the same machine that you’re developing on. You also need to modify the and elements we created earlier. See the bottom of the article for a full version of our build script.

When you start CruiceControl.NET again, you should see something similar to this output. Please beware that it can take a short while for the process to start.

clip_image032

As you can see, the script finds that there has been modification in the project inside our source control, which triggers a get process of the source code and later compilation and test-run.

You can specify your own trigger interval in the configuration file, depending on the size of your development team and your software, you can tune it to make sure you build often, but not so much that your build server starts having trouble.

You should create a special user account that your build process can run as and access the source control, as you can see in the example above I created a user called build.

Now it’s time to test the whole cycle of editing source code, check-in, watch the build server figure out there has been a modification and trigger a compilation and test-run. Let’s check out the Person.cs file and modify the age check to make our unit tests fail.

clip_image034

public bool IsOlderThan60()

{

  return (Birthdate > DateTime.Now.AddYears(-60));

}

When you’re checking code back into the source control system, it’s good practice to add an informative comment. This is useful for historical purposes and for other team members to get an overview of changes in the history view.

clip_image036

After checking in our changes, we only need to wait a few seconds to see that CC.NET discovers our change and runs our script.

clip_image038

Congratulations, you now have a CI-environment up and running!

Going Forward

We have looked at the base tools in a CI-environment, going forward I suggest taking a look at frameworks and tools that works good together with CC.NET. FxCop [8] is a tool from Microsoft that analyzes your assemblies and reports anything that is not according to the industry standards for naming conventions, etc. NCover [9] is a tool which will generate code coverage reports (that means it will highlight which application logic in your application is being covered by unit tests). If you’re a component shop, API documentation is important. Using tools like SandCastle [10] you can automatically generate help files from your XML comments.

There is a whole world to explore and the extension ability to your CI-environment is endless and everything is there to help you improve the process of building good software with high quality.

You should now understand how to setup your own CI-environment using free tools. Best of luck in setting up your own environment!

References:

[1] http://martinfowler.com/articles/continuousIntegration.html

[2]http://www.ericsink.com/scm/scm_intro.html

[3]

[4] http://nant.sourceforge.net/

[5] http://www.nunit.org/

[6] http://en.wikipedia.org/wiki/Test-driven_development

[7] http://www.sourcegear.com/

[8]

[9] http://www.ncover.com/

[10] http://www.codeplex.com/Sandcastle

Sample Soure Code (includes the ccnet.config build script):

IntegrationSample.zip

Build Script

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
 <project name="IntegrationSample">

  <triggers>
   <intervalTrigger seconds="60" />
  </triggers>

  <sourcecontrol type="vss" autoGetSource="true" applyLabel="true">
   <executable>C:\Program Files (x86)\Microsoft Visual SourceSafe\ss.exe</executable>
   <project>$/IntegrationSample</project>
   <username>build</username>
   <password>Password123</password>
   <ssdir>C:\Source\VSS</ssdir> <!-- Path to your SourceSafe database -->
   <workingDirectory>C:\Source\Samples\IntegrationSample\Build\</workingDirectory>
   <cleanCopy>false</cleanCopy>
  </sourcecontrol>

  <tasks>

   <msbuild>
    <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
    <workingDirectory>C:\Source\Samples\IntegrationSample\Build\IntegrationSample\</workingDirectory>
    <projectFile>IntegrationSample.sln</projectFile>
    <buildArgs>/noconsolelogger /p:Configuration=Debug /v:m</buildArgs>
    <targets>Build</targets>
    <timeout>720</timeout>
    <logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
   </msbuild>

   <nunit>
    <path>C:\Program Files (x86)\NUnit 2.4.8\bin\nunit-console.exe</path>
    <assemblies>
     <assembly>C:\Source\Samples\IntegrationSample\Build\IntegrationSample\Integration.Test\bin\Debug\Integration.Test.dll</assembly>
    </assemblies>
   </nunit>

  </tasks>
 </project>
</cruisecontrol>

—–

Sondre is a Microsoft Regional Director with 11 years of experience in software and web development. He currently works as Technology Leader for the Microsoft department at Capgemini in Oslo, Norway. Sondre is additionally the leader of the Norwegian .NET User Group in Oslo and a speaker at various technology and software development events. Active blogger, writer and technology enthusiast with a special passion for robotics, intelligent systems and open source.

Bring on the comments

  1. JB King says:

    Is there a reason for not mentioning Subversion as a means of source control? I find it much better than Visual Sourcesafe for version control and handling multiple checkouts and merges and branching/tagging.

  2. Derek says:

    JB,

    Sondre does say there are “many providers of SCM software; for the purpose of this article we will use Microsoft Visual SourceSafe.” The article he links to by Eric Sink lists several SCM options including Subversion and Vault.

    The Sink article is a number of years old and doesn’t cover more recent offerings including Git, Mercurial, and Microsoft Team Foundation source control.

`

Bad Behavior has blocked 247 access attempts in the last 7 days.