Archive for the 'continuous integration' Category

Published by breki on 13 Jan 2009

Automatic Software Publishing/Distributing Agent

This is a brainstorming post about an idea I’m toying with since morning.

The Problem

First let me describe the problem. Our team is into continuous integration (CI) and we are usually using multiple servers in the CI process: one for building the code and one for integration or acceptance tests. We usually use CruiseControl.NET project(s) to run the initial build and then push the build package onto an integration server (which also uses CruiseControl) to be tested thoroughly. This works, but the problem is writing and setting up scripts to wire all these things together. It boils down to several steps:

  • Packaging multiple files into a ZIP package.
  • Transferring the package to a remote location.
  • Unzipping the package there.
  • Executing a script or executable from the package.
  • Pushing the results somewhere else.

These steps apply for various procedures, from deploying software to running integration or GUI tests. So basically we have a package we want to run on a remote computer. My usual approach was to have a custom batch files on the remote computer which unzip the package and then run executables inside. The problem is that:

  • This is a custom solution for each individual situation. Every time we encounter another such scenario, new batch files need to be prepared.
  • It requires pre-installation (i.e. manually copying of these batch scripts to the right place) before the actual process can be started. And again, each scenario requires its own pre-installation.
  • CruiseControl.NET: although it is flexibile enough to allow this kind of usage, it is too cumbersome to set up.
  • Since the scripting code runs on physically separate locations, they it is also separated into multiple source code files, which means an additional effort is needed to maintain them (keep them in sync).

The Solution

What I was thinking about is some sort of a service (let’s call it Agent) that would accept requests for publishing certain files to a remote location and then running client-specified file(s). The Agent would have a .NET client library which would look like this:

using (IPublisher publisher = PublisherService.GetPublisher("remote_machine_name"))
{
    publisher.Publish(
        PublishingMode.ZippedFile,
        @"..\..\IntegrationTests.zip",
        @"C:\temp\IntegrationTests",
        @"RunTests.exe");
}

The Agent would of course have to be running on the remote machine. The client library would take care of zipping files into a single package (if necessary) and sending them to the remote publisher service. The remote publisher service would unzip the package to the requested location (in this case "C:\temp\IntegrationTests") and run the requested executable ("RunTests.exe"). Some things to note:

  • The call to Publish() would return after the files have been transferred to the remote computer. The actual execution on the remote machine would then proceed asynchronously.
  • There would have to be some kind of way to specify which user accounts have access to the Agent. Only those users would be allowed to publish stuff.
  • The executable would run under the Agent’s Windows service account.
  • I still haven’t figured out what kind of protocol to use to actually transfer the files (HTTP?).
  • The Agent should be able to run either from a command-line or as a Windows service (much like CruiseControl.NET does).
  • It should require the minimal effort to install, configure and maintain once it has been set up.

I should also note that Agents should only run on internal build/test servers, not production ones, since this kind of approach poses a considerable security risk – so I’m not saying it’s secure.

Final Thoughts

Agents would be installed only once and access configured for users that actually use them. After that the service would be available at all times to process various publishing requests of the CI process(es).

As I said from the start, this is just an idea. We’ll see if anything comes out of it ;)

Published by breki on 09 Jan 2009

MbUnit: Inconclusive Test Results

Questions
Creative Commons License photo credit: Oberazzi

UPDATE: Jeff Brown pointed me to a better way of doing some of the things discussed in this post, so I’ve updated the post.

One of the lesser known (and documented) features of MbUnit and Gallio is marking tests as inconclusive:

       [Test]
        public void InconclusiveTest()
        {
            if (WeDeterminedTheTestCannotBeRun)
               Assert.Inconclusive("Inconclusive message");

            WeThrowAnExceptionButItDoesNotMatter()
        }

By calling Assert.Inconclusive() we tell the test run it should mark this test case as inconclusive. Assert.Inconclusive() does not throw any exceptions, the tests continues to run, but even if the later code throws an exception or some assert fails, the test outcome will still be marked as inconclusive:

      456 run, 455 passed, 0 failed, 1 inconclusive, 1 skipped (1 ignored)

The build will not fail if we have one or more inconclusive tests. How does this come in handy? Sometimes you have tests which access certain external resources like internet pages. You want to be able to run such tests without causing the build to fail if internet connection is temporarily not available (I’m not saying that this is a good pattern for writing tests, just giving an example). One way to do this would be to first check the internet connection and mark the test as inconclusive if the connection is not available.

The second scenario (which we actually use in our acceptance test framework) is when you rely on certain test facility methods in order to execute the tests. Since these methods are often implemented in parallel with actual test code, we want to be able to mark them as not available until they are finished. We do this again by invoking Assert.Inconclusive() inside such methods, which will cause all test code that use these methods to have an inconclusive test result.

An alternative would be throwing NotImplementedExceptions, but we want to separate tests which actually failed from those which are not fully implemented.

There is a better way: Gallio: Setting Test Outcome Anyway You Like

Published by breki on 15 Dec 2008

Continuous Integration Builds – Do’s And Don’t's

IMG_0353

Since I haven’t posted anything on development stuff for a long time, I decided to write about something that I think is very important – doing continuous integration (CI) builds the right way. Below is a collection of advices I collected during the years regarding what to do and what to avoid when developing build scripts if you’re oriented towards CI principles:

  • DO make the main build procedure easy to run. Create a “Build.bat” batch file that will be obvious and simple to run. And place it in an obvious place. And make the main build target the default one. There’s nothing worse than spending the whole day looking around the code to find out how to build it (and this is a common problem once the main bulk of developers leave a project and someone else arrives a year later and is given a task of maintaining the project).
  • DO document the main build procedure. No Asimov’s Foundation series here, just a few lines of short sentences describing build targets. Or your could simply add “description” attributes to your NAnt/MSBuild targets?
  • DO use the same build steps for local (developer’s) builds and CI server builds. The developer must be able to verify the build before he/she commits the code to the repository. Having a different procedure running on CI server just means that sooner or later you’ll end up with half of your CI builds marked as failed because developers could not reproduce builds on their local machines.
  • DO keep the main (“indicator”) build running under 10 minutes. Developers need to be able to detect any problems with their code changes as soon as possible. Forcing them to sit around and wait for half an hour in order to get the feedback will only results in fewer commit cycles and more problems with integration. “Continuous” means continuous, not “I’ll do it after the lunch“.
  • DO separate the build procedure into several stages if your build takes longer than 10 minutes. The indicator build should make sure the code is built, analyzed, unit-tested and packaged. Everything else can be moved to next stage(s), so…
  • DO separate tests into unit and integration/acceptance tests. Unit tests typically work on isolated classes (typically using mocks) and do not use external resources like databases, Web services and similiar. This means they are fast, which makes them ideal for the first stage of the build. Integration tests: they test interactions between various parts of the system. Mocks are still used, but only to mimick certain external systems. These tests typically run on an actual database, which means setting them up and running them is slow and should be moved to the later stages of the build (or even moved physically to a different CI server so we can parallelize the build. While we’re on the subject…
  • DO use test categories to separate unit tests from integration tests. This way you can have both types of tests in the same assembly while telling the test runner (like Gallio or NAnt) to run only certain categories of tests.
  • DO select some of the important integration tests as “smoke” tests and run them before all other tests. This way you won’t have to wait for all of the tests to finish before detecting that the build has failed. The important thing is to make the build fail fast so that bugs can be fixed as soon as possible.
  • DO use FxCop, StyleCop and similar tools – and right from the start of the project. These tools can be a very useful way to auto-review the code of less experienced developers in the team. Which means less work for the project lead – he can concentrate on the substance of the code and leave the form to be polished by authors themselves. And FxCop can sometimes really discover bugs which would be difficult to detect otherwise.
  • DON’T rely on developer’s locally installed 3rd party libraries and tools to help you build the code. Instead, store all of the libraries and tools you need (OK, I’m not talking about VisualStudio and SQL Server here ;) ) under the source control and reference them from there. Also, communicate to the developers the potential problems of having these tools installed in GAC – GAC is your enemy! Why? By having the 3rd party stuff stored under the project’s source control, your team then has the control of which versions of these tools are actually used in the project. Since people tend to work on different projects (sometimes at the same time), relying on their local environment will mean that sooner or later there will be a conflict or a hidden bug because of different versions. From our experience there’s really no need for any of the commonly used stuff (NUnit, MbUnit, Gallio, NCover, Sandcastle, FxCop… just take a look at the lib directory of one of our open source projects) to be installed on the machine to be able to use it. One notable exception is TestDriven.NET, but then again, you don’t really use it to run builds from the command line.
  • DO separate the build script into a common one and the one specific for the individual project. This will make your common script reusable for other projects and you will also have a chance to polish the script in small steps. The project-specific script should just define the stuff that’s unique for the project (for example what files to include in the build package) and then just call the common script to do the rest of the work. You can see a sample common NAnt script and a project-specific script which I managed to construct in 2 years of working on different .NET projects). Feel free to abuse it. We’re moving to a different building tool anyway, but I’ll write about this some other time.
  • DON’T spam your developers! Do not send them e-mail messages for each successful CI build. Set the up CI server to send e-mail notification on failed and fixed builds only. This is the only way to make sure they are informed about problems with the build. Otherwise they’ll just ignore all CI e-mails altogether. 
  • DO treat the database as just a script. Some people think of databases as some evil deities which, once set up, should be left alone or they will inflict some horrible curses on the developer who dares to touch them. Databases are just text files containing the SQL code and data and should be stored under the source control. I would go even one step further and say that they should be recreated/re-migrated as part of each build. This of course means that every developer should have a database engine installed on their development machine. But this is the only way to make sure your .NET code and DB code are synchronized. And that your SQL scripts work! Some would say that they have huge databases with millions of records and they can’t afford to obliterate them 10 times a day, but I would ask them: do you really need 1 million user records to test the code for reading user records? Don’t confuse integration tests and performance tests. Performance tests are usually not part of the CI build because they take too long and setting them up can be a bit of a pain.

Useful links:

Published by breki on 31 Mar 2008

Tip: How To Speed-Up Sandcastle

Simply remove (or rename) the Data/Reflection directory, so that Sandcastle cannot find the information about .NET Framework libraries. You will loose the ability to have MSDN help on .NET Framework classes links in your documentation, but I think this is not crucial for day-to-day builds, compared to the substantial increase in your build speed. And also, by deleting the contents of the Reflection folder you’ll gain some 200 MB of space on your disk.

Published by breki on 07 Feb 2008

Tracking activity on your project in Subversion

A few months ago I was looking for some way of tracking activity on our new software project. What I wanted is a free and simple tool which could analyze Subversion logs and generate some statistics and graphs on lines of code, commits and similar stuff.

So I did a search on Google, SourceForge and some other search engines and I found two tools: StatSVN and (oddly enough) SvnStat. The latter generates a single HTML page with a collection of statistics graphs on daily commits (here is a sample report), while the former is more sophisticated and does analysis on lines of code, file and directory sizes, commit activity analyzed per hours of day and days of week and other things (see sample report). It even shows a repository heatmap – a clickable hierarchical map of your SVN repository with indicated increases or decreases of lines of code per directory or file.

The biggest difference between them is that StatSVN not only analyzes the SVN log file, but also goes through the latest version of your SVN repository. That’s how it calculates the lines of code in your project, for example.

I decided to use both of them, since they complement each other (SvnStat generates some graphs which the other one does not). I created a batch script and set it to run as a scheduled task on our build server. Here is a generalized version of the script, you have to fill in your specifics (see below):


PATH %PATH%;C:\Program Files\Subversion\bin
svn update <1>
svn log <1> -v –xml –non-interactive ><2>
cd D:\Programs\Development\SvnStat-1.0
java -classpath SvnStat-all.jar de.agentlab.svnstat.SvnStat -jar SvnStat-all.jar -r <2> -d <3>
cd D:\Programs\Development\statsvn-0.3.1
java -jar statsvn.jar -exclude <4> -output-dir <4> -cache-dir cache <2> <1>

<1> = a file path to your checked out repository

<2> = a place where you want to put the SVN XML log file (the whole file path including the name)

<3> = a place where the first (SvnStat) report will be generated

<4> = a place where the second (StateSVN) report will be generated

One warning: the reports also analyze activity for each SVN user, so watch out if you have members in your team that feel that this is a little too Big Brother-ish.

Published by breki on 31 Jan 2008

Generating WSDL documentation as part of the NAnt build

WSDLs are not very readable, so I wanted to have some sort of developer-friendly documentation for web services as part of our CI build. I found a simple but effective solution: WSDL viewer (by Tomi Vanek), which is an XSLT transformation file that produces nice HTML documentation.

I had to create a custom NAnt task for XSLT transformations since <style> task failed when I tried to do transformations using the WSDL viewer XSLT (it was complaining about some XML elements not being declared):


    <script language="C#" prefix="Brejc.NAntTasks.">
        <code>
            <![CDATA[
   [TaskName("xslt")]
   public class XsltTask : Task
   {
       [TaskAttribute ("inputfile", Required = true)]
       public string InputFile
       {
           get { return inputFile; }
           set { inputFile = value; }
       }

       [TaskAttribute ("outputfile", Required = true)]
       public string OutputFile
       {
           get { return outputFile; }
           set { outputFile = value; }
       }

       [TaskAttribute ("xsltfile", Required = true)]
       public string XsltFile
       {
           get { return xsltFile; }
           set { xsltFile = value; }
       }

       protected override void ExecuteTask ()
       {
           XsltSettings xsltSettings = new XsltSettings (true, true);
           XmlDocument xsltDoc = new XmlDocument();
           xsltDoc.Load (xsltFile);

           XmlUrlResolver resolver = new XmlUrlResolver ();
           XslCompiledTransform transform = new XslCompiledTransform (true);
           transform.Load (xsltDoc, xsltSettings, resolver);

           using (Stream inputStream = File.Open (inputFile, FileMode.Open, FileAccess.Read))
           {
               XmlReader reader = XmlReader.Create (inputStream);
               using (XmlWriter writer = XmlWriter.Create (outputFile))
                   transform.Transform (reader, writer);
           }
       }

       private string inputFile;
       private string outputFile;
       private string xsltFile;
   }
             ]]>
        </code>
        <references>
            <include name="System.Xml.dll"></include>
        </references>
        <imports>
            <import namespace="System.IO"></import>
            <import namespace="System.Xml"></import>
            <import namespace="System.Xml.Xsl"></import>
        </imports>
    </script>

Now all you need is to use this task to create the documentation:


    <target name="docs.wsdl" description="generates wsdl based on the existing web services">
        <mkdir dir="doc\wsdl" unless="${directory::exists(‘doc\wsdl’)}">
        <xslt inputfile="SomeWebService.wsdl">
              outputfile="doc\wsdl\SomeWebService.html"
              xsltfile="lib\WsdlViewer\wsdl-viewer.xsl"/>
    </xslt>
</mkdir></target>

Published by breki on 25 Jan 2008

Friday Goodies – 25 January

Development In General

.NET Development

OpenStreetMap

General

Published by breki on 14 Jan 2008

Keeping track of code comment warnings in your CC.Net builds

ccnetwarningstats.png

On the project I’m currently working on we are struggling to have all of public classes and methods documented. Since we haven’t been very disciplined doing that, we still have around 400 warnings related to code comments, which can be problematic since some more important warnings could be overlooked in this mass.

Since we already have CC.Net Statistics set up on our build server, I decided to use it to track compiler warnings so that we make sure their number not increasing with new builds. So here are instructions on how to set it up on your CC.Net build server.

(NOTE: we are using the old version of CC.Net Statistics which came before the codeplex project, so I’m not sure the same procedure applies to the new MSI-based version. I couldn’t make the new version run on our build server, I think it is probably because our CC.Net was installed manually and not using the MSI installation).

Okey, so the first thing to do is to tell CC.Net that your project should collect statistics about compiler warnings. Open your CC.Net project configuration file and find the <publishers> tag for the project. Insert the following XML code inside the <publishers> tag (it should be after the any <merge> publisher and before any <xmllogger> publishers):

<statistics> <statisticList> <statistic name=’Compiler Warnings’ xpath=’count(//*[contains (text(),"warning CS")])’/> </statisticList> </statistics>

If you already have the statistics publisher, just add the warning statistics line.

After saving the file, CC.Net should reload the configuration and start recording the statistics for the future builds. Now we have to add graphs for compiler warnings in CC.Net WebDashboard. Open the webdashboard\javascript\GraphConfiguration.js file in the text editor and find “var _recentGraphConfigurations” array. There you have to defined a new “recent graph” by adding the following lines:

//Compiler
{
   graphName: "Compiler",
   dataSource: _recentStatistics,
   numXTicks: _numberRecentGraphXTicks,
   series: [
      { name: "Warnings", attributeName: "Compiler Warnings", color: "green" }
   ]
},

You can choose your own title and color, off course.

To include warnings graph in the summary graphs page, first an function calculating the average warnings has to be added to the “var _summaryConfiguration” array:


//Compiler
compilerWarnings: function(successfulBuilds, failedBuilds) { return average(successfulBuilds, "Compiler Warnings") },

Now we have to add the summary graph to the “var _historicGraphConfigurations” array:


//Compiler        
{
   graphName: "Compiler",
   dataSource: _summarisedStatistics,
   numXTicks: _numberHistoricGraphXTicks,
   series: [
      { name: "Average Warnings", attributeName: "compilerWarnings", color: "green" }
   ]
},

After saving the file, don’t forget to restart the WebDashboard application in IIS (the easiest way is just to “touch” its Web.config file). After the next build, you should be able to see new graphs on your project statistics page.

« Prev