Test-Driven Development and Continuous Integration

46  Download (0)

Full text


Test-Driven Development

and Continuous Integration

We have all been there, working all night long on a specifi c piece of functionality, so happy that we've got something to run fi nally! We work to merge our code into the repository, pack our stuff, and fi nally head home. After spending 45 minutes in traffi c we get a phone call saying that "Whatever you checked in has somehow corrupted the entire code base!" No one can work now! We need you to come back and correct the issue. If you have been in this scenario then the odds are that you are not using test-driven development, continuous integration, or any form of build automation!

The simple idea behind working in a test-driven environment is that you prove that your code works, prior to actually writing the code. Then you write your code and modify your tests to better refl ect your code's intent. You refactor over and over till your code does what it is supposed to do. You end up with a solid code and proof that it works in the form of unit tests.

Down the road, having this proof in place would be a form of insurance in that it makes sure that your program works as you would expect it to. It is like having a second set of eyes constantly monitoring your code base for you. It is important because if you make a minor change to your code, or more likely, someone else makes a change to your code, your tests should catch it right away. This prompts you to either fi x the code that broke your tests or refactor your tests so that they correctly test your new code.

Unit Testing 101

Let's begin with unit testing now.


What is a unit test?

A unit test can be described as something that tests a specifi c unit of your program. Generally a unit test would thoroughly test all aspects of the smallest entity in your application throughout every entity in your application. An example of this would be tests for proving that a class works as you would expect it to.

A unit test is meant to thoroughly provide coverage for all the various aspects of the unit being tested. It is preferred that these tests are run in an isolated environment. This means that when testing widget A, you want to reduce dependence on widget B as much as possible, or remove all dependencies preferably.

What should I test?

Now the obvious question that crops up in one's mind is: what should be tested? Let's concentrate on that aspect.


Boundary checking is a way of testing that our application can handle itself. So if we were using some really fancy math object that say adds two numbers together and produces a result, we would want to make sure that it could add two small numbers without any issue like 1 + 1 = 2. Our object should be able to handle that. But let's pretend that our object is not set up to handle really large numbers. We would want to write a test of 9999 + 9999 = 19998 knowing that the test would produce an error because it did not support such large numbers. This test is to make sure that our code handles itself with regards to this error.

Success and failure

As we want to use our test as a way for us to prove that our code works as we would like it to, we would write a test that should pass—something like 1 + 1 = 2—that would produce true. The second step is to write a test that should fail—perhaps (1+ 1) > 2—that would produce false as a result. This has set the bounds for our application proving what works and what doesn't.


So now we know that our code can handle itself under duress. We also know that we have tests built around what we would expect our code to do and not to do. Now you would want to test the details of the specifi c functionality that your widget should perform (does your data layer connect to the database, does your XML parser parse XML, does your text reader read text, and so on.).


Using NUnit

While you can write tests around your code without any fancy tools, there are many free frameworks that greatly simplify the testing process. For .NET users the most widely known framework is NUnit. As long as you reference the NUnit DLLs in your project, you have full access to all that is offered by that framework.


The installation of NUnit is simple. Go to http://www.nunit.org and download their latest installation fi le. Once the download is complete, start the installation process and step through all of the screens that are presented.


Click Next.


Leave the defaults and select Next.


Once the installation is done successfully, you will see the following screen, where you click Finish.

Now that the installation is complete you will need to navigate to the NUnit

directory in the Program Files, or you can go through your start menu.

NUnit is not so much a program as a toolset to test your code. It does provide the NUnit GUI that you can run your tests from if you choose not to run the tests from inside Visual Studio (with ReSharper), with a build tool such as NAnt, or on the command line. They also provide a fair amount of example tests for you to take a look at.


Test-driven development (TDD)

Test-driven development (TDD) could be considered as Test First Development + Refactoring. The easiest way to think of TDD is that it is the blueprint for your functionality. You write tests to defi ne what your program is supposed to do. You then make your code perform according to that specifi cation. As your application grows, you will inevitably refactor your code base continuously. At this point all the tests you built around your code will now act as an early warning system keeping you from running into unseen obstacles below the surface of your application. Another nice side effect to developing this way is that you have expanded the concept of self-documenting code, that is, your tests defi ning clearly what your application can and can't do, or should and should not do.

Tests as a blueprint for your application

The basic idea behind how TDD works is that you write a very simple test (prior to writing any actual code) that should fail (as there is no code to test!). You then write the smallest amount of code to make that test pass now. After performing these two tasks you would then refactor your code to the next level and start again. Write another (additional) test that fails again followed by code to make it pass. In most environments, the easiest way to remember this is red light, green light, refactor.

Most testing frameworks operate similar to stop lights in that they provide red, green, and yellow icons for feedback!

Tests as an early warning system

Once you have written your entire application, you should have several tests around each piece of your application—the blueprint so to speak. We all know that as a company's focus changes with time. When that happens, the applications that they generally use need to be changed too. To you this means that your application will have to grow and change with the demand of the company. With any change to an application comes the opportunity for bugs. If you have all your tests in place and they are written correctly, a large amount of these buggy introductions should be caught with each build. When they are caught you would then decide if the change was appropriate, in which case the tests should be updated. Or in the case of a bug, the test is correct and the change was not implemented as intended—the code needs to be changed. Hence the early warning system. It will save you a lot of time if done right and is well worth the added time to maintain and grow your tests as your application grows.


Tests as documentation

Provided that your tests clearly defi ne what your application can and can't do, you have all the documentation that you should ever need (from a technical point of view) for your system. If there is any question as to what is done where, simply read through your (very descriptive) test method names and you should fi nd your answer.


Here is a very simple example of a math object where you add two numbers:

A test that fails:


public class MathTests {


public void ShouldReturnZeroWithoutInput() {

MyMath mm = new MyMath(); Assert.AreEqual(0, mm.Add()); }


Now of course, none of this will compile if we don't have a math object to work with! So let's make that real quick.

public class MyMath() {

public int Add() {

return -1; }


As we can see when the said test is run, it will try to do a dry run on the math object and receive a -1 (cheap hack to prove the point), which is not equal in any way to 0! This is our red light.

It is hard to see in black and white print whether the bar, icons, and various textual indicators are in a bold red. However, the circular warning icons and messages of failure are a clear indication that our tests did not pass!

A test that passes

Now, let's modify our code so that the test passes. We will do this by adding two properties for our inputs that the Add method will perform its operations on. Then in the Add method we will evaluate both the properties to see if either of them is 0.

public class MyMath() {

public int InputOne {get; set;} public int InputTwo {get; set;}

public int Add() {

return InputOne + InputTwo;


After making this small change we now have a test that successfully proves that this math object should return 0 if nothing is specifi ed in the input properties. If anything about this equation should change for some reason, our new test will alert us to the change the next time it is run.

As seen in the screenshot, the green doesn't exactly leap off this page, but that is ok. The icons are now check marks and the message is Success!

Using NAnt to automate your tests and


NAnt is more than just a test automation tool. It is an automation tool that is

capable of performing pretty much any repetitive task that you might fi nd yourself performing in the software development life cycle. I personally use NAnt to

automate the build process for my solutions, testing my applications, deploying the code to the QA and production boxes, team notifi cations, database updates, and so on. It is very versatile.

You should be aware that NAnt comes from the original Ant tool that Java

developers have used for so long. The concept has a lot of history. The history and the following of Ant is what has made NAnt such a fl exible tool.

NAnt is an open source tool that can be found at http://nant.sourceforge.net. To get started with this tool, download the installation fi le from http://sourceforge. net/project/showfiles.php?group_id=31650. You will see several different fi les here. If you are interested in looking at the source code for this project, go ahead and download the sourcefi le. Otherwise, just download the binfi le.


At the time of writing this, release 0.86 was in beta. For our discussions I will be using 0.85, which has proven to be quite stable.


I plan to cover the basics of getting this tool installed. However, if you fi nd my instructions too brief, you can fi nd a complete (and more importantly up-to-date) list of instructions here: http://nant.sourceforge.net/release/latest/help/


My instructions will be a bit different from what you will fi nd at that URL. I prefer to keep my Nant fi les directly with my project source code. This way, when a new person is added to the team they can simply get the latest. Moreover, not only will the project fi les get downloaded, but will also have all the automation tools up and running with no additional confi guration.

To get started, let's open up our project's trunk directory. In here we will need to create a new folder, which I usually call bin or binaries. For this project, I have gone with the name binaries. Inside your binaries directory, create a NAnt folder. Now open up the fi le that you downloaded (something like nant-0.85-bin.zip). Then extract all the fi les you see into the newly-created NAnt folder.

Before you forget, commit the new structure and fi les into your repository!

That's it for the installation of NAnt. Now comes the fun stuff! Let's get NAnt confi gured to work in your development environment.


There are really two primary parts to confi guring NAnt to run smoothly—

confi guring NAnt to automate your solutions with a build fi le and running NAnt from a batch fi le.

NAnt configuration files

NAnt is very fl exible. It uses a simple XML fi le, much like any other confi g fi le that you see in the .NET environment. This XML fi le ends with a .build extension though. Although you can specify which fi le NAnt will use, the .buildfi le is what NAnt would normally look for if not specifi ed.


Let's get started by adding another directory to our trunk folder called build. In the build directory, we will keep our NAnt .build fi le (the XML confi guration fi le that tells NAnt what to do), our batch fi les, results from the build process, and so on. Oddly enough, everything to do with the build process!

Let's create the buildfi le. I called mine Fisharoo.build. Open that fi le up and let's add some basic XML so that NAnt can get busy. I posted the entire basic confi guration fi le here so that you can get the 50,000 foot view. I will discuss the basics next. A lot of this should be fairly self-explanatory though.

To make your life a lot easier, you should be aware that there is a schema

fi le out there for Visual Studio. This fi le (nant.xsd) allows Visual

Studio's intellisense to help guide you through all the various options of NAnt. Great for the FNG's out there! This fi le should be located in the initial download that you get for NAnt. Place that fi le in program fi les| Microsoft Visual Studio X.0 | xml | schemas and restart Visual Studio.

<?xml version="1.0" encoding="utf-8"?>

<project name="FisharooWeb" default="build" xmlns="http://nant.sf.net/ release/0.85/nant.xsd">

<property name="trunk.dir" value="..\"/>

<property name="company.name" value="Fisharoo"/>

<property name="bin.dir" value="..\Source\FisharooWeb\bin" /> <property name="build.dir" value=""/>

<property name="results.dir" value="${build.dir}\Results" /> <property name="project.name" value="FisharooWeb" />

<property name="version.major" value="1"/> <property name="version.minor" value="0"/> <property name="version.build" value="0"/> <property name="version.revision" value="0"/> <property name="project.fullversion"


${version.build}.${version.revision}" dynamic="true" /> <property name="database.dir" value="..\Databases"/>

<property name="database.server" value="localhost\sqlexpress"/> <property name="database.name" value="Fisharoo"/>

<property name="versioneddatabase.dir" value="${database.dir}\VersionedCopy"/> <property name="localdatabase.dir" value="${database.dir}\LocalCopy"/> <property name="currentFramework" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5"/> <!-- default configuration -->


<!-- debug|release -->

<target name="compile">

<echo message="Build Directory is ${build.dir}" /> <exec program="${currentFramework}\msbuild.exe" commandline="..\Source\FisharooWeb.sln /t:Clean /v:q" workingdir="." /> <exec program="${currentFramework}\msbuild.exe" commandline="..\Source\FisharooWeb.sln /t:Rebuild /v:q" workingdir="." /> </target> </project>

There are many books and sites out there that do a great job of going over NAnt build fi les. The fi rst place that you should start is at the NAnt homepage (http://nant.sourceforge.net/). I will briefl y cover the basics though.

The fi rst part of my buildfi les are reserved for property defi nitions. These are much like any other name-value pair that you have worked with before. It is a good idea to put any value that might need to be changed in a property so that it is easy to get to and adjust down the road. Values you will see in this buildfi le are for items such as directory locations, app names, and so on. The properties can then be referenced with:


You should be aware that the NAnt executable runs everything from your build fi le's physical location. This is great. It is one reason I put the NAntfi les in the build directory so that it is quick and easy to point to your project's resources! This is the reason why you will see trunk.dir property, which points one directory up the build directory where our build fi le is run from.

Once you work your way through all the property defi nitions, you will get to the meat and potatoes of NAnt—target defi nitions. Targets are an OOP way of thinking. They compartmentalize a unit of work—a task so to speak. Targets can have

prerequisite targets (referred to in the depends call out). This means that if Target A depends on Target B, Target B will be executed prior to Target A. This allows you to chain your targets.

Once you have a target defi ned, you can defi ne tasks. You can really do just about anything in your targets. If NAnt or the command line doesn't provide that perfect functionality that you are looking for, you can always create your own widget and tell NAnt how to run your new functionality.

In our example, you will see that we output some text to the command line as a message and then execute an MSBuild process on our Fisharoo solution.


MSBuild is the tool that Microsoft ships, which allows you to build your code via the command line. This means that a developer doesn't really need Visual Studio to develop MS code!

If we had tests in our solution, we could also call out those tests and have NAnt run the NUnit tests as part of the build (we don't currently have any tests!) If we did, we would add a section to our NAnt script (inside of a target section) to execute those tests, which looks something like this:

<nunit2 failonerror="true" verbose="true">

<formatter type="Xml" outputdir="${results.dir}" usefile="true" extension=".xml"/> <formatter type="Plain" /> <test assemblyname="${trunk.dir}\source \FisharooCoreTests\bin\Debug\ Fisharoo.FisharooCoreTests.dll" directory()}nant.tests.config"/> </nunit2>

NAnt and batch files

NAnt is a command line tool. This means that you would normally open up the command prompt and manually type commands that you would have NAnt execute for you. LAME? I am specifi cally using NAnt so that I don't have to do any manual tasks. So I usually automate (batch fi le) the automation (NAnt build fi les) to avoid any manual labour. Let's see how this works.

In this build directory let's add two more fi les. The fi rst fi le we will create is the build.batfi le—our base batch fi le. And fi nally we will create a clickToBuild.bat fi le, which passes parameters to our build.batfi le.

You can make as many of these secondary .batfi les as you need.

You could have a clickToDeploy.bat, a moveToQA.bat, a

cleanDatabase.bat, and so on. The sky is the limit with helper fi les! The build.batfi le is easy. It is basically some easy command line arguments. It looks something like this:

..\binaries\nant\nant.exe -buildfile:Fisharoo.build %*

This one line is all there is to the build.batfi le. It basically states that we will fi nd an instance of the NAnt executable one directory up and inside the binaries | nant folder. It then goes on to tell NAnt which build fi le to use. After that we would


normally tell NAnt which target to execute in our buildfi le. In our case though, we specify the percentage sign and an asterisk. The percent and asterisk characters at the end of the line allow us to pass additional arguments into NAnt from another batch fi le, which allows us to reuse the basic entry points across multiple batch fi les, allowing us to easily execute different build processes. Let's see this in action! Let's create the next fi le (if you didn't already). This one will be called

clickToBuild.bat. I am guessing you know what this fi le will do already? Here is an example of what will go in this fi le:

build.bat compile & pause

This line of code calls our previous batch fi le (which we know gets NAnt ready for us). It then passes in the name of the target that we want to execute. In our case, we want to call the compile target. Look at the Fisharoo.buildfi le shown under section NAnt confi guration fi les and you will see that the target has a name attribute, which has a value of compile.

Now let's test our setup by clicking on the clickToBuild.batfi le. You should see something like this:


While this is a very basic example of NAnt building some code, I think you get an idea of what NAnt is capable of. Take a look at the buildfi le in this project's completed state for ideas.

Now that we have some of our build process automated, what can we do to automate it even more? Read on.

Using CruiseControl.NET to automate

your automation

CruiseControl.NET is an automated continuous integration platform. It allows you to automate the build and test processes on your development server to essentially enforce that your code base stays in good condition at all times. If, for some reason, the code base does fi nd itself in a dirty state, CruiseControl.NET can make everyone aware of it so that its broken state is quickly rectifi ed.

Continuous integration (CI) is a concept whereby when a developer checks the code in, it not only merges into the code base as a fi le overlay but also passes through the build process without errors (and for those in a TDD environment, the new code would also need to pass all the tests). This helps in keeping your code base clean and usable! A team that runs in a CI environment will usually live by the motto "check in often". Preferably don't go home for the day without checking in all your modifi cations. The further you get from the current code base, the more likely it is that the need for a merger will rear its ugly head.


The installation of CruiseControl.NET is fairly easy. It is another open source project that is freely available. You can get it here: http://confluence.public.

thoughtworks.org/display/CCNET/Download. Once you have it downloaded to


Double-click the downloaded installation fi le.


Click I Agree to continue.

I accepted the default installation. This will not only install the CruiseControl.NET integration server, but will also provide you with the Web Dashboard, which allows you to see what is going on with your build processes in a browser. It also installs some samples to look at. Click Next.


If you plan to run this server in a production environment, then you will want to install it as a Windows service. This means that the service will be started when the machine is started and should run until the machine is stopped (or the service is manually stopped). If you want to use the dashboard, then allow the install to create a virtual directory for you. Click Next.

I accepted the default location. You can also put the installation somewhere else. Then, click Next.


Just in case you wanted to change the name of what you see in your programs listing, here is your chance to do it! Click Install and watch the magic.

You should now see the installer installing various fi les into your machine. Click

Next when the install is completed. Then click Close. Is that it? I wish it were that easy.

To start off we need to go into ISS and verify that the version of .NET that is being used is 2.0 as the Web Dashboard is a 2.0 application. To do this, go into your

start menu | program fi les (or) control panel | administrative tools | internet information services (IIS) manager. Once that management console opens up, navigate into your default website | ccnet (application) and right-click Properties. Then click the ASP.NET tab. Make sure that the ASP.NET version is set to 2.0 and hit OK.


Now back in the management console, right-click on the ccnet application again and select permissions. If you don't see the ASP.NET account and the NETWORK SERVICE account, add those as well. You can do that by clicking the Add button.


Then click the Advanced button.

Click the Find Now button to get a list of all the users on your server. Select the ASP. NET and NETWORK SERVICE accounts and click OK.


You should have something as shown in the immediately preceding screenshot. Click OK.

You should now have the ASP.NET and NETWORK SERVICE accounts in your security listing. For a dev environment you can give these accounts Full Control. If you are setting up your production environment refer to your Network Administrators guidance on setting permissions. Click OK.


Now right-click on the ccnet application one more time and select the Browse

option. If you have confi gured your server and directory security appropriately, you should now see a window similar to this:

Note that while we got the app working, there is still a message stating that the dashboard was unable to connect to the CruiseControl.NET service. Let's fi x that! Again, go into the start menu | program fi les / control panel | administrative tools | Services. In this window, locate the CruiseControl.NET entry.


You will notice that the service is installed as manual and is not started. Double-click the CruiseControl.NET entry.

Set the startup type to Automatic. Then click the Start button to start the service. Then click OK. We should be good now.

You can verify if the service is running correctly or not by going back into IIS and browsing to the ccnet application. You should now see something like this:



Now that we have CruiseControl.NET installed and running on your server, let's tell it what we want it to do. In your start menu, navigate to the newly-created

CruiseControl.NET entry and click on your CruiseControl.NET Confi g item. This will open an empty confi guration fi le.

This confi guration fi le is stored in the CruiseControl.NET directory in your Program Files directory.

Trust me—you will be putting a lot of time into the construction of this

fi le over time. So I suggest that you maintain a copy of this fi le inside your repository—probably best kept in the build directory. This way you will get all those wonderful versioning features that your repository offers. Edit the repository version and copy the changes over the server's copy as you need to.

Let's start building this fi le. We will discuss the various sections in a second. For now, here is the fi le in its entirety:


<project name="Fisharoo">

<labeller type="defaultlabeller" />

<webURL>http://ccnet.fisharoo.com/ccnet/ViewFarmReport.aspx</webURL> <sourcecontrol type="filtered">

<sourceControlProvider type="svn" autoGetSource="true">

<executable>C:\data\projects\Fisharoo\trunk\binaries\subversion\ svn.exe</executable> <trunkUrl>http://andrew-sjx124ut:8080/svn/Fisharoo.com/trunk</ trunkUrl> <workingDirectory>C:\data\repositories\Fisharoo.com</ workingDirectory> <tagOnSuccess>false</tagOnSuccess> <tagBaseUrl>C:\data\projects\Fisharoo\tags\</tagBaseUrl> <username>[username]</username> <password>[password]</password> </sourceControlProvider>


<inclusionFilters> <pathFilter> <pattern>**/*.*</pattern> </pathFilter> </inclusionFilters> </sourcecontrol> <tasks> <nant> <executable>C:\data\projects\Fisharoo\trunk\binaries\nant\nant. exe</executable> <baseDirectory>C:\data\projects\Fisharoo\trunk\source\</ baseDirectory> <buildArgs>-D:svn.executable="C:\data\projects\Fisharoo\trunk\ binaries\subversion\svn.exe"</buildArgs> <nologo>false</nologo> <buildFile>C:\data\projects\Fisharoo\trunk\Build\fisharoo. build</buildFile> <targetList> <target>cruise</target> </targetList> <buildTimeoutSeconds>1200</buildTimeoutSeconds> </nant> </tasks> <publishers> <merge> <files> <file>C:\data\projects\Fisharoo\trunk\Build\Results\*.xml</ file> </files> </merge> <xmllogger /> <statistics /> <email from="FisharooBuild@fisharoo.com" mailhost="mail.fisharoo.com" includeDetails="TRUE"> <users>

<user name="Andrew Siemer" group="buildmaster" address="asiemer@fisharoo.com"/> <user name="Jessica Siemer" group="buildmaster" address="jlsiemer@fisharoo.com"/> <user name="Anatoliy Mamalyga" group="buildmaster" address="amamalyga@fisharoo.com"/> <user name="Kenny Tongkul" group="buildmaster" address="ktongkul@fisharoo.com"/>


<user name="Arturo Moreno" group="buildmaster" address="amoreno@fisharoo.com"/> </users>


<group name="buildmaster" notification="always"/> </groups>

</email> </publishers> </project> </cruisecontrol>

I will walk you through some of these nodes and their attributes, but a better source of information can be found here: http://confluence. public.thoughtworks.org/display/CCNET/Project+Configur ation+Block This is by no means a complete reference on this topic!


The labeller is what takes care of your revision numbers, or build numbers. In our case, we are using the defaultlabeller type. This will simply increment the build numbers each time the build occurs. You can confi gure this section further by adding a prefi x, and so on.


The webURL is the path to reporting for a project. It is used by CCTray and the Email Publisher.


Go to the following link:

http://confluence.public.thoughtworks.org/display/CCNET/Subversion+So urce+Control+Block

This section defi nes how CruiseControl.NET should communicate with your repository. CruiseControl.NET is able to speak with many different types of repositories. I will cover the SVN confi guration in a short while.


This section tells CruiseControl.NET which type of repository to communicate with. In our case we will specify SVN.



This is a path to the SVN executable so that CruiseControl.NET can perform actions on the repository.


This is the path to the trunk directory of your source code as SVN would communicate with it. It is usually the server name | project name | trunk.


This is the local location that SVN will use to check out the working copy of the repository.


This determines whether or not SVN will tag check-ins upon a successful build.


This is the base URL for your tags in your repository.


It is important to specify the username and password for an SVN installation. If you get an "authorization failed" error message, look to these tags (or lack thereof) for the fi x to your issue.


This determines which modifi cations should be included. In our case, we are allowing everything.


The tasks section of the confi g fi le allows you to specify the functionality for

CruiseControl.NET to perform. You can perform all sorts of tasks. For a complete list take a look at:


nant (task)

The nant task is the one we will use most. This allows us to keep most of the functionality in our NAnt build fi les where we have the most control.


This tag maintains the path to the NAnt executable so that CruiseControl.NET knows where to go to perform these tasks.


The baseDirectory tag tells NAnt where to go to fi nd the source code for our projects.


The buildArgs tag allows us to pass in extra NAnt parameters as though we were running NAnt from the command line. In our case, we are passing in the location of the SVN executable for NAnt to be able to perform SVN related tasks.


This is another NAnt property that needs to be passed so that NAnt has a defi nition of the tasks to be performed.


The targetList section defi nes targets that are in your NAnt build fi le so that NAnt knows which of your targets to act on. In our case, we are telling NAnt to trigger the "cruise" target. From this point, NAnt executes a target as normal, meaning it executes the dependent targets.

If you have been following along, you will notice that our NAnt Fisharoo.buildfi le doesn't currently have the "cruise" target. Open your Fisharoo.buildfi le and insert this new target as defi ned in the following code snippet:

<!-- default configuration -->

<property name="project.config" value="release" /> <!-- debug|release -->

<target name="cruise" depends="compile" />

<target name="compile">

<echo message="Build Directory is ${build.dir}" /> <exec program="${framework}\msbuild.exe"


This target, named "cruise", requires that the "compile" target is executed fi rst. Rather than just calling compile directly from within CruiseControl.NET (which we could have done), we have defi ned a separate entry point, which will give us greater fl exibility down the road.


This specifi es how long you are willing to let the entire build process take. If you fi nd that you are going over your acceptable limit, look at reducing the execution time of your unit tests rather than continuing to increase this timeout. Also, you may want to look at removing dependencies on external resources with the use of mocked objects.


The publishers section allows CruiseControl.NET to interact with external log fi les, the log fi les it generates, and how to send emails.

Keep in mind that you need to specify all your external application logs (using merged fi les), CruiseControl.NET xmllogger, and statistics prior to defi ning your email section. The reason being that you won't have access to the data while creating the email if the other areas are not yet defi ned!

publishers and merge

This tag grouping allows CruiseControl.NET to have access to the output logs of other tools such as NAnt, NUnit, and so on, so that the output can be included in the web control panel or in the ccnet emails.


In this section, you can identify the path to the fi les you want to be used by CruiseControl.NET.

publishers and xmllogger

The xmllogger is used to create the log fi les from CruiseControl.NET.


publishers and statistics

This section allows you to gather some basic statistics about your builds. You will want to defi ne this section after your merge section so that you can pick up some statistics from your other sources. This too should be defi ned prior to your email section so that the gathered statistics can be sent in your notifi cations.

publishers and email

The email section allows you to send out automatic notifi cations to your

development team and management staff. Remember to include this section below all the resources that you might want mentioned in your email alerts such as the xmllogger, statistics, and merged fi les.

In this section, you can defi ne the server and the account to be used for sending your email as well as the username/password for that account. You can then defi ne the users who will receive notifi cations and the groups that each user belongs to. After that you can defi ne each group and the frequency at which each group receives notifi cations.

Let's test out the installation and


Now that we have CruiseControl.NET installed and confi gured on our server, let's see if it works. There are a few ways to check on this:

1. Execute the command line tool located at C:\Program Files\

CruiseControl.NET\server. Then you can check the ccnet.logfi le for the results. You may want to set the error output level to DEBUG to get a verbose amount of information from the process.

2. Open a command prompt. Navigate to the CruiseControl.NET\server directory.


3. Then enter ccnet.exe and hit enter. I don't have room to show the entire output of this window, but you should see a bunch of data stream by.

4. Once you have this running you can then look into your ccnet.log fi le. It will have any errors, successes, and so on.


5. With the CruiseControl.NET service running, you can also watch the ccnet. logfi le. In this case, you might want to set the error output level to DEBUG in the ccservice.exe.config.

Another place to look for issues is in the web dashboard. Here you can force a build to occur, watch its status, and view its results. Keep in mind this will only work if you have the xmllogger confi gured in your ccnet.confi g fi le to capture all the output!


Click the "here" link to view the current status.

If you had any errors you could view their details in the "Recent Builds" section. One might look something like this.

Given that this is a webpage, you will have to scroll left to read the error. But you do have the entire error message available to you.


And if your installation and confi guration is mostly correct, you will get email notifi cations containing the build status.

After performing all this debugging, make sure that you remember to toggle the error output mode in your confi guration fi les away from DEBUG. DEBUG is verbose and outputs everything! This will rapidly bloat your log fi les.

Once your debugging has proven that your CruiseControl.NET installation is working as you would expect it to, you can then make sure that your CruiseControl. NET windows service is running in automatic mode so that each time your box is rebooted, the service comes back up too.

Some things to be aware of

Some of the issues that I ran into were easily fi xed, but might need some explanation here.

trunkUrl values:

I found that the documentation for trunkUrl suggested that I use the svn://server/project/trunk notation. This did not work for me. I got an error stating that the connection was refused. To fi x this issue I used http://server/project/trunk. This fi xed the connection refused error but then produced an authentication error. To fi x this, I then specifi ed the username/password tags. Depending on how you have your security set up on the server, you may be able to use anonymous authentication.


.NET Framework:

Please make sure that the .NET Framework that you use on your dev machines are installed and confi gured on your build server. I am using .NET 3.5 and C# 3.0. I am also using the latest AJAX, web applications, and so on with these projects. While I had .NET 3.5 installed, I found that this did not provide the full framework that my projects required. To fi x this, I installed the entire Visual Studio 2008. This may not be a requirement by any means to fi x an include issue—I am sure you can simply install the referenced DLLs and be done with it! I chose to do this so that I could edit the source on my server when I am away from my dev boxes, and fi x the issue as well. Web Dashboard:

The web dashboard is a .NET 2.0 application, which is installed in your default website (in IIS) as the "ccnet" application. Make sure that your

security is appropriately confi gured for your development team to access the site. Also make sure that the .NET version that is used by that site is a fl avor of .NET 2.0.

Using CCTray to watch CruiseControl.NET


After you have had CruiseControl.NET installed for a while you will notice that you get a lot of email notifi cations! Some people like this. Others prefer to keep the number of emails they receive in the course of a day to a minimum. If you are an email minimalist, you should take a look at the CCTray program that comes with CruiseControl.NET. You can either get this program from your CruiseControl.NET installation, or you can get it by navigating to your web dashboard. Once you have the executable downloaded locally, you can get to installing it.



The installation of CCTray is very simple. Double-click the downloaded install package.


Click I Agree.


Click Next.


The installation process shouldn't take more than a couple of minutes.


Click Finish.

Once your installation is complete, you should have an icon in your system tray that is a green circle with the letters CC.

Adding projects to CCTray

Double-click on the CCTray icon in the system tray so that we can connect it to the repository.


Click the Add button.


Leave the default selection of Connect directly using .NET remoting. In the text box, you can either keep the default, that is, localhost, or you can provide your server's name. Click the OK button.

You should now see your server and the projects that are installed on that server. In our case, we connected to the www.fisharoo.com server, which has a Fisharoo project. Select the Fisharoo project and click the OK button.


Click the OK button.

At fi rst you should see the CCTray trying to connect to your server. During this time you will have a gray icon.

If everything was installed and confi gured correctly, you should eventually get the green icon with the last build statistics! Now that you have this program installed, you can double-click on the project name and jump directly to the web dashboard. Now that this program is installed, you can always keep a real time eye on the code base and build. When someone checks the code in, you will see that a build is occurring (indicated by yellow icons) and the activity of building.


If the build were to fail, the icons would turn red. If the build was in the process of executing while in a broken state, you would have an orange icon stating that the build is still broken.

If you fi nd that the visual notifi cations are not good enough, you can also confi gure CCTray to give you audible notifi cations by going to File | Settings | Audio (tab).


We have discussed unit testing and how it will help provide you an early warning system for modifi cations to your code. Then we went over NUnit, and how it will help you in the creation of your unit tests. Once we had some tests to play with, we discussed NAnt and how it helps automate your building and testing processes. Finally, we discussed CruiseControl.NET and how it can help you fi nish off the automation aspects, so that any time someone modifi es your code base, the building and testing of the code is automatically kicked off in addition to providing various forms of notifi cation to your development team.

I am hoping that I overwhelmed you with enough information for this topic to fascinate you. With any luck, the testing and automation bug will get under your skin in the same way that it happened with me. If set up correctly, these tools can really help you maintain a stable code base as well as provide your development team with an additional form of collaboration.