    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Testing Visiting Files and Directories in C#</title>
        <link>https://members.accu.org/index.php/articles/1472</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #83 - Feb 2008</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c237/">83</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-237/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+237/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Testing Visiting Files and Directories in C#</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 12 February 2008 08:55:00 +00:00 or Tue, 12 February 2008 08:55:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Testing code that accesses the file system is not straightforward. Paul Grenyer looks at what is involved.</p>
<p><strong>Body:</strong>&nbsp;  <p>In my previous article, 'Visiting Files and Directories in C#' [<a href="#VFDC#">VFDC#</a>], I looked at how to use C# to remove a source tree and developed the code into an enumeration method [<a href="#EnumMethod">EnumMethod</a>] and visitor [<a href="#Visitor">Visitor</a>] compound that can be used for general purpose file and directory traversal (Listing 1).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
    public interface IDirectoryVisitor
    {
      void EnterDirectory(DirectoryInfo dirInfo);
      void VisitFile(FileInfo fileInfo);
      void LeaveDirectory(DirectoryInfo dirInfo);
    }
    public class DirectoryTraverser
    {
      private IDirectoryVisitor visitor;
      public DirectoryTraverser(
      IDirectoryVisitor visitor)
      {
        this.visitor = visitor;
      }
      public void Traverse(string path)
      {
        Traverse(new DirectoryInfo(path));
      }
      private void Traverse(DirectoryInfo dirInfo)
      {
        visitor.EnterDirectory(dirInfo);
        foreach (
         DirectoryInfo subDir in
         dirInfo.GetDirectories())
        {
          Traverse(subDir);
        }
        foreach (FileInfo file in dirInfo.GetFiles())
        {
          visitor.VisitFile(file);
        }
        visitor.LeaveDirectory(dirInfo);
      }
    }
  </pre>
  </td></tr><tr><td class="title">Listing 1</td></tr></table>
  <p>
    The article did not discuss any form of automated testing. This not only makes me very uncomfortable, it also means the classes cannot be modified or refactored safely. In this article I am going to look at how to write automated tests for <tt class="code">DirectoryTraverser</tt> and discuss the differences between unit and integration testing and when to use them.
  </p><h2>
    Unit and integration testing
  </h2><p>
    The message about automated testing is finally getting through. However, many organisations are still not doing it. The majority of those that are using automated tests cannot see past unit testing or their unit tests are a mixture of unit tests and integration tests. I'm going to use an example to demonstrate the difference between a unit test and an integration test and explain when each should be used and more importantly when unit tests should not. Despite what some fanatics may refuse to concede, it is not always appropriate or sensible to use a unit test and can often introduce unnecessary complexity or volume code for little or no gain, especially in noticeable performance.
  </p><p>
    Imagine you have a class, called <tt class="code">HistoricPrices</tt>, that is used to retrieve historic stock prices from a database. The class constructor takes an <tt class="code">IDBConnection</tt> interface that is used to make direct calls to a database to retrieve the prices. A test is run every time the project containing <tt class="code">HistoricPrices</tt> is compiled by the developer on their local machine. The developer needs the test to run quickly and give accurate repeatable results, so instead of passing in a real <tt class="code">DBConnection</tt> (the class that implements <tt class="code">IDBConnection</tt> in production) object they pass in a fake [<a href="#Fake">Fake</a>]. The fake object has a number of hard-coded recordsets that are mapped to a set of predetermined SQL strings. This means that every time a particular SQL string is executed via the <tt class="code">IDBConnection</tt> interface to the fake object, the same recordset is always returned. As the fake object does not actually talk to the database the recordset is returned in (almost) zero time. This makes the tests very fast and easy to run. This is a <span style="  font-style: italic; font-weight: normal; vertical-align: baseline">unit</span> test.
  </p><p>
    The unit test only tests a very small part of the system, in this case just one class. Every system should be tested as fully as possible. In the case of <tt class="code">HistoricPrices</tt> the interaction with a real database is vital and should also be tested. The developer still requires the tests to give accurate repeatable results, so instead of using a live database a test database is constructed, tested against using the production <tt class="code">DBConnection</tt> object and torn down every time the test is run. The test takes some time to run and tests the interaction between a <tt class="code">HistoricPrices</tt> object and a real database. This is an <span style="  font-style: italic; font-weight: normal; vertical-align: baseline">integration</span> test.
  </p><p>
    In my experience, creating and dropping a SQL Server database on a developer spec machine can take anything up to 20 seconds. That is a long time to wait, so the developer is likely to be less keen to run the test every time they compile. Therefore the integration test should be run, at the very least, prior to a release and ideally prior to checkin, as part of a nightly build of the entire system and/or as part of continuous integration [<a href="#CI">CI</a>].
  </p><p>
    So, to recap, unit testing is about removing dependencies and writing tests that run in (almost) zero time, so that they can be run every time the compiler is invoked. Integration tests test the interaction between at least two things. For example between two objects or between an object and a database or an object and a file. This means that integration tests potentially take a while to run and traditionally this puts developers off running them every time they invoke the compiler.
  </p><h2>
    Unit testing DirectoryTraverser
  </h2><p>
    The only parts of the .Net library that intrude into <tt class="code">DirectoryTraverser</tt> are <tt class="code">DirectoryInfo</tt> and <tt class="code">FileInfo</tt>. So all that needs to be done to write a unit test is to mock these out and create a suitable factory to create the mocks when testing and the real objects when in production. The problem is that <tt class="code">DirectoryInfo</tt> and <tt class="code">FileInfo</tt> do not already have suitable interfaces, so new interfaces must be written and the original classes wrapped. That in itself is not too much trouble. Unfortunately <tt class="code">GetDirectories</tt> and <tt class="code">GetFiles</tt> methods return a <tt class="code">DirectoryInfo[]</tt> and <tt class="code">FileInfo[]</tt> respectively and therefore their return values must be mapped onto arrays of the new interface types. Suddenly you have much more test code than code being tested and it is far more complex, so a unit test is not appropriate or worthwhile in this case.
  </p><h2>
    Integration testing DirectoryTraverser
  </h2><p>
    As previously stated, integration testing is the testing of how one or more units or modules work together. In the case of <tt class="code">DirectoryTraverser</tt> we need to test how it integrates with the file system. This involves creating a known set of directories and files, traversing them, checking the results and, of course, cleaning up afterwards.
  </p><h2>
    Creating directories and files
  </h2><p>
    Before we consider how to create directories and files we must consider <span style="  font-style: italic; font-weight: normal; vertical-align: baseline">where</span> to create them. It needs to be a place where the following test code can find them and where they won't interfere with anything else in the file system. We could just pick a path, such as c:\temp, but that would only work on Windows machines. .Net has the ideal solution:
  </p>
<pre class="programlisting">
      Path.GetTempPath()
</pre><p>
    The <tt class="code">GetTempPath</tt> method returns the path to a directory that can be used to store temporary files and directories. The path is specific to the operating system in use. So on Windows it's something along the lines of:
  </p>
<pre class="programlisting">
 C:\Documents and Settings\user\Local Settings\Temp
</pre><p>
    And on Linux it's along the lines of:
  </p>
<pre class="programlisting">
     /home/user/tmp

</pre><p>
    Now we're ready to create the directories and files. .Net makes this very easy as both the <tt class="code">Directory</tt> and <tt class="code">File</tt> classes have create methods that take a string:
  </p>
<pre class="programlisting">
      // Creating a directory.
      Directory.CreateDirectory(&quot;...&quot;);
      // Creating a file
      FileStream str = File.Create(&quot;...&quot;);
      str.Close();
</pre><p>
    The only thing to remember is that the <tt class="code">File.Create</tt> method returns an open <tt class="code">FileStream</tt> and must be closed so the file can be accessed in the test, as you cannot rely on <tt class="code">Dispose</tt> being called in time.
  </p><p>
    As well as using different temporary paths, different operating systems also use different directory separators. The <tt class="code">Path.Combine</tt> method will concatenate <span style="  font-style: italic; font-weight: normal; vertical-align: baseline">two</span> strings together with the correct separator for the operating system. So, for the path
  </p>
<pre class="programlisting">
      test\dir1\dir2
</pre><p>
    you would need to write:
  </p>
<pre class="programlisting">
      string fullPath = &quot;test&quot;;
      fullPath = Path.Combine(fullPath, &quot;dir1&quot; );
      fullPath = Path.Combine(fullPath, &quot;dir2&quot; );

</pre><p>
    This is more than a little tedious, especially for long or multiple paths, and is not especially clear. It would be much nicer to be able to write:
  </p>
<pre class="programlisting">
      string fullPath = MakePath(&quot;test&quot;, &quot;dir1&quot;,
         &quot;dir2&quot;);
</pre><p>
    The C# <tt class="code">params</tt> keyword allows methods to take a varying number of arguments and access them as an array, which in turn allows us to write:
  </p>
<pre class="programlisting">
      static private string MakePath(
         params string[] tokens)
      {
        string fullpath = &quot;&quot;;
        foreach (string token in tokens)
        {
          fullpath = Path.Combine(fullpath, token);
        }
        return fullpath;
      }
</pre><p>
    All that's left is to define the directories and file we want to create. This is easily and clearly done using arrays (Listing 2).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
    string testFolderPath = Path.GetTempPath();
    string[] testDirs = {
      MakePath(testFolderPath, &quot;Test&quot;),
      MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;),
      MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;, &quot;dir2&quot; ),
      MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;, &quot;dir2&quot;,
       &quot;dir3&quot;) };
    string[] testFiles = {
      MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
       &quot;file1.txt&quot;),
      MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
       &quot;file2.txt&quot;),
      MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;, &quot;dir2&quot;,
       &quot;file3.txt&quot;),
      MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;, &quot;dir2&quot;,
       &quot;file4.txt&quot;) };
  </pre>
  </td></tr><tr><td class="title">Listing 2</td></tr></table>
  <p>
    I have chosen a very simple directory structure: A root directory called Test with two nested subdirectories, dir1 and dir2, each containing two text files file1.txt, file2.txt, file3.txt and file4.txt and a further empty subdirectory, dir3. This allows us to test that <tt class="code">DirectoryTraverser</tt>:
  </p><p>
    Creating the files and directories is easily accomplished using a couple of foreach's:
  </p>
<pre class="programlisting">
   // Create directories
      foreach (string dir in testDirs)
      {
        Directory.CreateDirectory(dir);
      }
      // Create files
      foreach (string file in testFiles)
      {
        FileStream str = File.Create(file);
        str.Close();
      }

</pre><p>
    The directories and files should be removed after the test. This can be achieved using the <tt class="code">Directory.Delete</tt> method and setting the recursive flag (see Visiting Files and Directories in C#):
  </p>
<pre class="programlisting">
      Directory.Delete(testFolderPath + &quot;Test&quot;, true);

</pre><p>
    Finally the create and delete code needs to be put into the <tt class="code">SetUp</tt> and <tt class="code">TearDown</tt> methods of an NUnit [<a href="#NUnit">NUnit</a>] test fixture (Listing 3).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
    [TestFixture]
    public class DirectoryTraverserTest
    {
      private readonly string testFolderPath =
       Path.GetTempPath();
      static private string MakePath(
       params string[] tokens)
      {
        string fullpath = &quot;&quot;;
        foreach (string token in tokens)
        {
          fullpath = Path.Combine(fullpath, token);
        }
        return fullpath;
      }
      [SetUp]
      public void Setup()
      {
        Directory.CreateDirectory(testFolderPath);
        string[] testDirs = {
          MakePath(testFolderPath, &quot;Test&quot;),
          MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;),
          MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;,
           &quot;dir2&quot;,
          MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;,
           &quot;dir2&quot;, &quot;dir3&quot;)  ) };
        foreach (string dir in testDirs)
        {
          Directory.CreateDirectory(dir);
        }
        string[] testFiles = {
          MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
           &quot;file1.txt&quot;),
          MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
           &quot;file2.txt&quot;),
          MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
           &quot;dir2&quot;, &quot;file3.txt&quot;),
          MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
           &quot;dir2&quot;, &quot;file4.txt&quot;) };
        foreach (string file in testFiles)
        {
          FileStream str = File.Create(file);
          str.Close();
        }
      }
      [TearDown]
      public void TearDown()
      {
        Directory.Delete(testFolderPath,true);
      }
    }
  </pre>
  </td></tr><tr><td class="title">Listing 3</td></tr></table>
  <p>
    This is the best of many options I considered for creating the directories and files. Other options included:
  </p>
		<ul><li>
    Traversing XML to get the structure.
  </li><li>
    Storing the structure in a zip file that would be extracted each time the test was run.
  </li><li>
    Writing the structure to an output file and using an external tool for test verification.
  </li></ul><p>
     The advantage of the final solution is that it is simple and all in the code with no need for an external XML file, zip file or external tool.
  </p><h2>
    Test Visitor
  </h2><p> <tt class="code">DirectoryTraverser</tt> won't do anything without a visitor. Of the four tests listed in the previous section, 1 is the easiest to implement. All that is needed is a stack. When <tt class="code">EnterDirectory</tt> is called the directory path is pushed onto the stack. When <tt class="code">LeaveDirectory</tt> is called, a path is popped from the stack and compared to the path of the directory just left. As long as they are the same the test passes (Listing 4).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
    class DirRecorder : IDirectoryVisitor
    {
      private Stack&lt;string&gt; lastDir   =
       new Stack&lt;string&gt;();
      public void EnterDirectory(
         DirectoryInfo dirInfo)
      {
        lastDir.Push(dirInfo.FullName);
      }
      public void VisitFile(FileInfo fileInfo)
      {
      }
      public void LeaveDirectory(
         DirectoryInfo dirInfo)
      {
        Assert.AreEqual(
         lastDir.Pop(), dirInfo.FullName);
      }
    };
  </pre>
  </td></tr><tr><td class="title">Listing 4</td></tr></table>
  <p>
    To run the test, an instance of the visitor must be created and passed to an instance of <tt class="code">DirectoryTraverser</tt>. Then the <tt class="code">DirectoryTraverser</tt> instance must be passed the path to traverse:
  </p>
<pre class="programlisting">
      [Test]
      public void TraverseDirectory()
      {
        string testPath = Path.Combine(
           testFolderPath, &quot;Test&quot;);
        DirRecorder dirRecorder = new DirRecorder();
        DirectoryTraverser trav =
           new DirectoryTraverser(dirRecorder);
        trav.Traverse(testPath);
      }
</pre><p>
    The easiest way to ensure that all file and directories are entered and all files are visited is to create a list of both and compare them to lists of expected directories and files. The order in which directories are entered and files are visited is not guaranteed, so all lists must be sorted. The expected lists can be generated at the same time as the physical directories and files are created (the highlighted code in Listing 5 shows the modifications).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
	 [TestFixture]
	 public class DirectoryTraverserTest
	 {
		  private List&lt;string&gt; expectedDirs =
		   new List&lt;string&gt;();
		  private List&lt;string&gt; expectedFiles =
		   new List&lt;string&gt;();
	   ...
	   [SetUp]
	   public void Setup()
	   {
		 ...
		 foreach (string dir in testDirs)
		 {
			  expectedDirs.Add(dir);
		   Directory.CreateDirectory(dir);
		 }
			expectedDirs.Sort();
		 ...
		 foreach (string file in testFiles)
		 {
			  expectedFiles.Add(file);
		   FileStream str = File.Create(file);
		   str.Close();
		 }
		 expectedFiles.Sort();
	   }
	   ...
	 }
  </pre>
  </td></tr><tr><td class="title">Listing 5</td></tr></table>
  <p>
    The visitor can be modified to keep a list of entered directories and visited files, and accessors provided to retrieve the lists. Again, highlighted code in Listing 6 shows the modifications.
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 class DirRecorder : IDirectoryVisitor
 {
      private List&lt;string&gt; dirs = new List&lt;string&gt;();
      private List&lt;string&gt; files = new List&lt;string&gt;();
   private Stack&lt;string&gt; lastDir =
    new Stack&lt;string&gt;();
      public List&lt;string&gt; Dirs
      {
        get
        {
          dirs.Sort();
          return dirs;
        }
      }
      public List&lt;string&gt; Files
      {
        get
        {
          files.Sort();
          return files;
        }
      }
   public void EnterDirectory(
      DirectoryInfo dirInfo)
   {
        dirs.Add(dirInfo.FullName);
     lastDir.Push(dirInfo.FullName);
   }
   public void VisitFile(FileInfo fileInfo)
   {
        files.Add(fileInfo.FullName);
   }
   public void LeaveDirectory(
      DirectoryInfo dirInfo)
   {
     Assert.AreEqual(
      lastDir.Pop(), dirInfo.FullName);
   }
 };
  </pre>
  </td></tr><tr><td class="title">Listing 6</td></tr></table>
  <p>
    Then the <tt class="code">TraverseDirectory</tt> test can be modified to compare the lists of visited directories and files with the expected lists (Listing 7).
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
 [TestFixture]
 public class DirectoryTraverserTest
 {
   private readonly string testFolderPath =
    Path.GetTempPath();
   private List&lt;string&gt; expectedDirs  =
    new List&lt;string&gt;();
   private List&lt;string&gt; expectedFiles =
    new List&lt;string&gt;();

   static private string MakePath(
    params string[] tokens)
   {
     string fullpath = &quot;&quot;;
     foreach (string token in tokens)
     {
       fullpath = Path.Combine(fullpath, token);
     }
     return fullpath;
   }

   [SetUp]
   public void Setup()
   {
     Directory.CreateDirectory(testFolderPath);

     string[] testDirs = {
       MakePath(testFolderPath, &quot;Test&quot;),
       MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;),
       MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;,
        &quot;dir2&quot;),
       MakePath(testFolderPath, &quot;Test&quot;,&quot;dir1&quot;,
        &quot;dir2&quot;, &quot;dir3&quot;) };

     foreach (string dir in testDirs)
     {
       expectedDirs.Add(dir);
       Directory.CreateDirectory(dir);
     }
     expectedDirs.Sort();

     string[] testFiles = {
       MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
        &quot;file1.txt&quot;),
       MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
        &quot;file2.txt&quot;),
       MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
        &quot;dir2&quot;, &quot;file3.txt&quot;),
       MakePath(testFolderPath, &quot;Test&quot;, &quot;dir1&quot;,
        &quot;dir2&quot;, &quot;file4.txt&quot;) };
     foreach (string file in testFiles)
     {
       expectedFiles.Add(file);
       FileStream str = File.Create(file);
       str.Close();
     }
     expectedFiles.Sort();
   }
   [Test]
   public void TraverseDirectory()
   {
     string testPath = Path.Combine(
      testFolderPath, &quot;Test&quot;);

     DirRecorder dirRecorder = new DirRecorder();
     DirectoryTraverser trav =
      new DirectoryTraverser(dirRecorder);
     trav.Traverse(testPath);

        Assert.AreEqual(
         expectedDirs, dirRecorder.Dirs);
        Assert.AreEqual(
         expectedFiles, dirRecorder.Files);
   }
   [TearDown]
   public void TearDown()
   {
     Directory.Delete(
        testFolderPath + &quot;Test&quot;,true);
   }
 }
  </pre>
  </td></tr><tr><td class="title">Listing 7</td></tr></table>
  <p>
    This completes the implementation of the integration test for DirectoryTraverser. Running the test with the NUnit console gives the  output shown in Figure 1.
  </p>
  <table class="sidebartable"><tr><td>
  <pre class="programlisting">
    NUnit version 2.4.3
    Copyright (C) 2002-2007 Charlie Poole.
    Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
    Copyright (C) 2000-2002 Philip Craig.
    All Rights Reserved.

    Runtime Environment -
       OS Version: Microsoft Windows NT 5.1.2600 Service Pack 2
      CLR Version: 2.0.50727.832 ( Net 2.0.50727.832 )

    .
    Tests run: 1, Failures: 0, Not run: 0, Time: 0.188 seconds
  </pre>
  </td></tr><tr><td class="title">Figure 1</td></tr></table>
  <p>
    The NUnit GUI gives the satisfying green bar. I successfully ran this test on both Windows XP and SuSE [<a href="#SuSE">SuSE</a>] Linux under Mono [<a href="#Mono">Mono</a>].</p><h2>
    Acknowledgments
  </h2><p>
    Thank you to Kevlin Henney for guidance and sanity checking and the members of accu-general for healthy discussion on testing techniques. Thank you to Caroline Hargreaves, Roger Orr and Adrian Fagg for review.
  </p><h2>
    References
  </h2><p class="bibliomixed">
    [<a name="#CI"></a>CI] Continuous Integration: <a href="http://en.wikipedia.org/wiki/Continuous_Integration">http://en.wikipedia.org/wiki/Continuous_Integration</a>
  </p><p class="bibliomixed">
    [<a name="#EnumMethod"></a>EnumMethod] <a href="http://www.two-sdg.demon.co.uk/curbralan/papers/ATaleOfThreePatterns.pdf">http://www.two-sdg.demon.co.uk/curbralan/papers/ATaleOfThreePatterns.pdf</a>
  </p><p class="bibliomixed">
    [<a name="#Fake"></a>Fake] <a href="http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs">http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs</a>
  </p><p class="bibliomixed">
    [<a name="#Mono"></a>Mono] <a href="http://www.mono-project.com/">http://www.mono-project.com/</a>
  </p><p class="bibliomixed">
    [<a name="#NUnit"></a>NUnit] <a href="http://www.nunit.org/">http://www.nunit.org/</a>
  </p><p class="bibliomixed">
    [<a name="#SuSE"></a>SuSE] <a href="http://www.novell.com/linux/">http://www.novell.com/linux/</a>
  </p><p class="bibliomixed">
    [<a name="#Visitor"></a>Visitor] Design patterns: elements of reusable object-oriented software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. ISBN-10: 0201633612 ISBN-13: 978-0201633610
  </p><p class="bibliomixed">
    [<a name="#VFDC#"></a>VFDC#] Visiting Files and Directories in C#. <a href="http://www.marauder-consulting.co.uk/articles.php">http://www.marauder-consulting.co.uk/articles.php</a>
  </p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
