I hate to digress from the raw TDD discussion so early on, but if you're serious about TDD, you have to consider whether continuous integration (CI) is right for you or not. Even if you aren't doing TDD or unit testing, many teams will find CI useful. For example, if your team is split up across the world (or even the country) the last thing you want is for Team B to have to deal with Team A's broken build. Of course, CI isn't only useful for geographically challenged teams. If I had to guess, I'd say you'll easily make up the initial time investment.
For n00bs to CI, the point is to ensure your code is always buildable and that all unit tests always pass. Basically, a CI solution hooks into your source control server, detects that a change was made, and rebuilds/retests your code automatically. The most common solution, CruiseControl.NET comes with a system tray utility that warns you when something goes wrong. In other words, if anyone breaks a build or makes a test fail, you're little icon turns red and you'll get a bubble warning. From there, you can opt to see detail information about what exactly failed and fix it!.
CruiseControl.NET simply monitors your source control repository, it's NAnt that actually builds and runs your code. The last time I was personally responsible for setting up NAnt was a couple years ago and it was a real pain. Now I see that they have a Solution task that makes everyone's life easier. The last thing I want to do is write a tutorial for CruiseControl.NET and NAnt, but I do want to share my configuration files, in case they help someone else
<project name="OLMD" default="build" basedir=".">
<property name="releaseMode" value="debug" overwrite="false" />
<property name="baseDir" value="c:\builds\" overwrite="false" />
<property name="deployDir" value="${baseDir}olmd\" overwrite="false" />
<property name="reportDir" value="${baseDir}reports\olmd\" overwrite="false" />
<property name="projectDir" value="${deployDir}\olmd\" overwrite="false" />
<target name="build">
<vaultgetfile url="http://s1"
username="username"
password="pass"
repository="Fuel"
path="$/1/Fuel/"
destination="${deployDir}/Fuel"/>
<vaultgetfile url="http://s1"
username="username"
password="pass"
repository="Fuel"
path="$/1/Olmd/"
destination="${deployDir}"/>
<solution configuration="${releaseMode}" solutionfile="${projectDir}\olmd.sln" />
<call target="test" />
<call target="clean" />
</target>
<target name="clean" description="remove all generated files">
<delete dir="${deployDir}" />
</target>
<target name="test" failonerror="true">
<nunit2>
<formatter type="Xml" usefile="true" extension=".xml" outputdir="${reportDir}" />
<test assemblyname="${projectDir}\olmd\bin\${releaseMode}\Fuel.Projects.Olmd.dll" />
</nunit2>
</target>
</project>Basically, the Build target (which is default), checks out 2 projects from Vault, and uses the wonderful Solution task to build everything. The Test target then uses the nunit2 task to run my unit tests with all reports sent to a global report directory. Finally, everything's cleaned up.
The CruiseControl.NET configuration is even simpler (mostly because I copied and pasted most of it from the CC.NET website):
<cruisecontrol>
<project name="OLMD">
<webURL>http://s2/ccnet/</webURL>
<triggers>
<intervalTrigger seconds="30" />
</triggers>
<modificationDelaySeconds>10</modificationDelaySeconds>
<sourcecontrol type="vault" autoGetSource="false" applyLabel="false">
<executable>c:\program files\sourcegear\vault client\vault.exe</executable>
<username>user</username>
<password>pass</password>
<host>s1</host>
<repository>fuel</repository>
<folder>$/1/</folder>
<ssl>false</ssl>
<useWorkingDirectory>false</<useWorkingDirectory>
</sourcecontrol>
<tasks>
<nant>
<executable>C:\builds\Nant\bin\nant.exe</executable>
<baseDirectory>C:\builds\Nant-Config\</baseDirectory>
<<buildArgs/>
<buildFile>olmd.build.xml</buildFile>
<targetList>
<target>build</target>
</targetList>
<buildTimeoutSeconds>300</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<merge>
<files>
<file>C:\builds\reports\olmd\*.xml</file>
</files>
</merge>
<xmllogger />
</publishers>
</project>
</cruisecontrol>Here we tell CC.NET to use Vault and how to use it (you can get this extension from SourceGear's website for free) and tell it what to do when it detects a change - namely to run our NAnt build script above. The last thing to do is point it to the reports NAnt created.
I seem to remember this being a much bigger pain to set up, but this time it didn't take more than 1/2 an hour to set up (I had a bug in CC.NET which I eventually fixed by disabling all versions except 2.0). With CI in place, we're ready to continue TDD'ing.
Posted
Mon, Jun 26 2006 10:26 AM
by
karl