I am going to talk to you about continuous integration; some people prefer the term continuous build. I will not be going into depth about integrating entire systems but will concentrate on the integration of individual classes and assemblies that make up one distinct application.
CruiseControl.net is the application which I will be discussing in particular. At its most basic, it can be used simply to create automatic builds which can at least prove that the application will compile on a development server and not just on the developer’s own desktop.
Setting up continuous integration for a project does take some time and effort but the end result is that you can be much more lazy: just let the automated process do it all for you.
So why would you want to implement continuous integration in the first place? Well, it eliminates many of the concerns regarding integrating code that has been created by individual developers and then has to be integrated into the final application. By building the application on a clean machine, any missing files or dependencies will be instantly recognised as these will cause the build to fail. Continuous integration need not stop at just building the software. It can also automate unit testing (e.g. Nunit), code coverage (e.g. Ncover) which indicates the amount of code that is actually being tested by unit test, documentation (e.g. Sandcastle) and standards compliance (e.g. fxCop) amongst others.
Now you can begin to see the real value of this automation. Developers can feel much more assured that the code they check into source control will build and, provided that it has adequate code coverage, it doesn't break any other code in the process.
I must point out that this process does not test the display of the GUI, it only tests the functionality. As such, it cannot replace all manual testing but it does cover a great deal.
Using the Code
N.B. Names of servers, UNC paths and URLs have been disguised throughout this article for reasons of security. Likewise the paths in the example files are fictional. You will need to replace references to "myServer" and "MyDirectory" as appropriate to your installation.
TeamCity by JetBrains is great for large scale projects where you need the ability to allow many teams to modify the configuration of the Build engine. However, as this is an introduction to continuous integration, I have chosen to use CruiseControl.net, it is free and easy to use.
The Web Dashboard is an ASP.NET application running on IIS. It provides you with details about all your builds including reports and stats on individual builds. See screen grab below:
Here is an example of a unit testing stats page:
Here is a build report:
CruiseControl.net comes with a client side application which is shown in the sys tray and can be viewed via a double click on the icon:
Here is the application:
OK, in this window you will see four separate builds. The bottom three builds have been created for just one application. I will discuss these three as they are the most interesting.
SSE Main Build simply builds the application in its entirety. It runs every 30 seconds looking for any new code that has been checked into source control.
SSE-NightlyBuild creates a version of the application that is the latest build which can be run on the server itself. It also performs all unit tests. This runs at 1am every day.
SSE-Documentation simply creates all the documentation from the comments.xml files created when each assembly is built. This relies on the developer adequately commenting his/her code using XML comments and predefined tags preceding any method or property.
You can choose to view as many builds as you wish and they do not have to be on the same CruiseControl.net server. To do this, select Settings by right clicking on the CCTray icon:
Now you can add a CruiseControl.net server and any builds it has that you wish to monitor.
If any or all of the builds are currently building, the icon changes colour to orange. When a build is complete, the icon is either green for successful or red when there has been an error. The same colour keys are used in the Cctray window itself.
Nant / MsBuild
In order to create these builds, you will need to write some build scripts. I have used nant Version 0.85. This is not the latest version but I encountered some problems with a later version and as this one does the job, I've stuck with it.
Please take a look at SSE.build (included file) You will notice that I have included building the comments.xml files for each target. Also, the .NET assembly named UnitTests is called separately. This is because the project is not included in the release build of the solution but in the debug build.
I also encountered a problem with registry keys whilst using msbuild. This is the workaround:
Edit the registry adding sdkInstallRootv2.0 to
and point it to the folder where the sdk exists on that computer e.g.
Copy lc.exe to the bin subdirectory of the sdkInstall folder if it isn't there already
N.B. There is no need to do the above unless you encounter problems.
Sandcastle is Microsoft’s tool to automate the documentation of classes by creating a *.chm file and MSDN like pages.
In order to build documentation for all the assemblies, you will need to edit the Sandcastle.config file adding additional data files elements. Please see lines 74-93 in the sandcastle.config file.
Next you need to write a nant script to call Sandcastle. This is quite complex so I have included the example
I am a fan of unit tests, they can be a bit of a chore to create but I consider them as necessary as the use of source control and most developers would agree that would be hard to think of life without that.
Apart from simply making sure that your code does what it says on the tin, unit testing can be very useful when you wish to test your application in isolation from any other system that it communicates with. I have used NUnit to test this application without the need of the server. It also does the tests much more swiftly as I am reading from local files containing dummy data rather than waiting for the results of SOAP calls to the server.
Principals of Unit Testing
Atomic tests – each test should test one property or method only and with one and one only expected result. A new test should be made for each method or property with additional tests for the boundaries of each.
Test cases – unit tests can be written to prove test cases. These are tests that are based on specific use cases. For example, if a use case consisted of a user logging into an application viewing some data and logging off, then the test case should follow these same steps.
I have chosen to put all my unit tests in one assembly as this makes the test automation very easy, however you might choose to create separate assemblies for each logical tier or layer of your application. This adds a bit to the automation but it does mean that your components remain discrete and developers can run the tests independently.
The nunit framework comes with its own MockObject but doesn't support things like events and generics. You could take a look at Rhino Mocks instead. I haven't used it but it gets good reviews.
Test driven development is where you write the unit tests first and then the code to be tested after. This focuses your mind on the exact details of regarding the purpose of each method and it can help to prevent the creation of unneeded code. It does take a bit of a change of mindset and the problem is trying to get back into it after doing some bug fixing that doesn't require a unit test.
Maybe it is optimistic to imagine that a developer will have time to write unit tests for existing code. Visual Studio 2005 Team edition does provide a Unit test wizard which will create the basis of the unit tests, so lightening the work load. Maybe there is some other open source application out there that does something similar.
As there are already so many articles around on unit testing and NUnit in particular, I do not see the value of going into detail here. Suffice it to say that automating your tests makes sure that they do get run regularly.
You will see that Nunit is called directly from CruiseControl.net itself using the tag <nunit> as a child of <tasks> in the SSE-NightlyBuild project in the file ccnet.config.
Tasks Needed to Get CruiseControl.net Working on a New Server
This presumes that you are using a Windows server:
Getting the WebDashBoard Working with IIS
Make sure that ASP.NET is installed on server: Go to add/remove programs, add/remove Windows components, select Application Server, then click on Details. Make sure that ASP.NET is ticked.
If you installed IIS after the .NET Framework was installed, you need to register ASP.NET with IIS. You can do this by running the aspnet_regiis.exe -i tool found under \Windows\Microsoft.NET\Framework\v2.0.50727\.
In IIS Admin, go to Web Service Extensions and make sure that ASP.NET v2.0.* is allowed and any other version prohibited.
- 7th March, 2009: Initial post