Sunday, May 09, 2004

The last few days have been very exciting for MbUnit. I have been working (remotely) with Jamie Cansdale, creator of NUnitAddIn, to create a Visual Studio Add-in for MbUnit. It turned out to be surpringly simple, thanks to the extensible architecture of NUnitAddIn and the expertise of Jamie.

A quick NUnitAddIn introduction

NUnitAddIn is not just an Add-in for NUnit as it's name seems to tell. It is far more than that. It is a extensible framework to build Add-ins. All the words are important here: extensible, because it is designed to accept any type of Add-in (at least test runners) and framework because it takes care of all the complicated/technical task of launching processes, attaching debuggers, etc. In fact, writing an Add-in with NUnitAddIn is as simple as implementing an interface!

Add-in How-to

I will give here a detailled how-to on the Add-in creation. This is the summary of few hours of coding and dozens of MSN messages with Jamie Cansdale (very active support!). Now let's go for the fun (I will assume you have NUnitAddIn installed in c:\Program Files\NUnitAddIn)

Setup the project

  1. Create a new Assembly project and name it as you like. In this example, it will be named MbUnit.AddIn
  2. Add the following references
    • NUnitAddIn.TestRunner.dll
    • NUnitAddIn.TestRunner.Framework.dll
  3. Change to ouput directory to the NUnitAddIn directory: Projet -> Properties -> Common Properties -> Output Path -> Select NUnitAddIn directory
  4. Make the assembly strongly named

Setup NUnitAddIn

You need to edit NUnitAddIn.config in the NUnitAddIn directory (do not edit NUnitAddIn.exe.config). The file looks like this:

<?xml version="1.0"?>
<configuration>
  <nunitaddin>
    <frameworktestrunners>
      <testrunner name="NUnit"
                     typeName="NUnitAddin.NUnit.TestRunner.SimpleNUnitTestRunner" 
                     assemblyPath="NUnitAddin.NUnit.dll"  />
      ...
    </frameworktestrunners>
  </nunitaddin>
</configuration>

Add your Add-in on top of the "food chain":

<?xml version="1.0"?>
<configuration>
  <nunitaddin>
    <frameworktestrunners>
      <testrunner name="MbUnit"
                     typeName="MbUnit.AddIn.MbUnitTestRunner" 
                     assemblyPath="MbUnit.AddIn.dll"  />
      <testrunner name="NUnit"
                     typeName="NUnitAddin.NUnit.TestRunner.SimpleNUnitTestRunner" 
                     assemblyPath="NUnitAddin.NUnit.dll"  />
      ...
    </frameworktestrunners>
  </nunitaddin>
</configuration>

Every is now setup. NUnitAddIn will use the MbUnit.AddIn.MbUnitTestRunner class as test runner.

Getting started with ITestRunner

The last step of the job is to implement ITestRunner. We will name our runner accordingly to the name with have putted in the config file.

  1. Create the class
    using NUnitAddIn.TestRunner.Framework;
    
    public class MbUnitTestRunner : ITestRunner, MarshalByRefObject
    {...}
  2. Tag the class with the assemblies used by your test runner using the DependencyAttribute attribute. For MbUnit there are quite a few:
    [
    DependentAssembly("NUnitAddin.TestRunner"),
    DependentAssembly("NUnitAddin.TestRunner.Framework"),
    DependentAssembly("QuickGraph.Exceptions"), 
    DependentAssembly("QuickGraph.Concepts"),
    DependentAssembly("QuickGraph.Predicates"),
    DependentAssembly("QuickGraph.Collections"),
    DependentAssembly("QuickGraph.Representations"),
    DependentAssembly("QuickGraph.Algorithms"),
    DependentAssembly("QuickGraph.Serialization"),
    DependentAssembly("QuickGraph"),
    DependentAssembly("MbUnit.Core")
    ]
    public class MbUnitTestRunner : MarshalByRefObject, ITestRunner
    
    The two reference to NUnitAddin.TestRunner and NUnitAddIn.TestRunner.Framework are obligatory.
  3. Make the object "long living" by making InitializeLifetimeService return null:
    public class MbUnitTestRunner : ITestRunner, MarshalByRefObject
    {
        public override Object InitializeLifeTimeService()
        {
            return null; 
        }
    }
  4. ITestRunner define two methods, Abort and Run. Abort does not need to be implemented, so yoiu can throw a NotImplementedException in it. Run is where the job is done.
    public void Abort() 
    { 
        throw new NotImplementedException(); 
    } 
    
    public TestResultSummary Run( 
        ITestListener testListener, 
        ITraceListener traceListener, 
        string assemblyPath, 
        string testPath 
    ) 
    {
        ...
    }
    In the Run method, testListener is used to send test results to NUnitAddIn, ITraceListener is used to ouput messages to the console window, assemblyPath is the path to the test assembly and testPath is a string describing what has to be tested formatted as follows:
    ('N' | 'T' | 'M') : Type
    For example, values of testPath can be
    • N:MyTests.Tests, the namespace (and sub-namespaces) MyTests.Tests has to be run,
    • T:MyTests.Tests.SimpleFixture, the class SimpleFixture has to be run,
    • M:MyTests.Tests.SimpleFixture.SomeTest, the method SimpleFixture.SomeTest has to be run
    • null, the entire assembly is run
  5. Let's start with an "hello world" test runner:
    public TestResultSummary Run( 
        ITestListener testListener, 
        ITraceListener traceListener, 
        string assemblyPath, 
        string testPath 
    ) 
    {
        traceListener.WriteLine("Hello World!");
    }
    

We are ready to make the first run of the Add-in. Open you dummy test project and right click either on the assembly, on a namespace, a type or a method and hit the "Run Tests..." rocket. If everything goes to plan, you should something like this appear in the output window:

------ Test started: Assembly: MbUnit.Tests.dll ------
Hello World!
---------------------- Done ----------------------

If you are lucky it worked out-of-the box, otherwize the next section deals with the Add-in debugging.

Debugging the Add-in

Different failure can appear at different levels. I have encountered several but hopefully, I had Jamie on my back helping me all the way. Here's a simple procedure:

  1. Add a break point on the "Hello World" line inside the Run method,
  2. Right-click on a test class, choose Test With... -> Debugger. If you are lucky, the debugger will hit the break point and you can do "classic" debugging.
  3. If the debugger did not hit the break point, it is likely that NUnitAddIn failed to load the Add-In. You need to make the debugger break on exceptions:
    1. go to Debug -> Exceptions
    2. choose Commmon Language Runtime
    3. When exception is thrown, break into debugger
  4. Run the tests again, this should give you the exception that make the Add-in loading fail.

Important note: when you recomile your project, you may have an error saying the assembly file cannot be copied because it is used by another process. At this point, you need to restart NUnitAddIn. To do this, right click on the rocket icon in the taskbar and click "Close". Recompile and yes it works!

Implementing the Run method

The rest of the work is mainly up to you. You need to load the assembly, look for the test fixture according to the "testPath" and execute them. The important thing is that the notification is done throught ITestListener.

Just for the fun, here's the output of the Add-in on the TestFixtureTest in MbUnit.Tests assembly:

------ Test started: Assembly: MbUnit.Tests.dll ------
C:\Documents and Settings\Peli\Mes documents\Tigris\mbunit\src\MbUnit.Tests\bin\StrongDebug\MbUnit.Tests.dll: [mbunit] Test Execution
[mbunit][setup] Load C:\Documents and Settings\Peli\Mes documents\Tigris\mbunit\src\MbUnit.Tests\bin\StrongDebug\MbUnit.Tests.dll assembly.
[mbunit][setup] Exploring types for fixtures.
[mbunit][setup] Setup Successfull, starting 1 tests.
[fixture] TestFixtureAttributeTest
[start] TestFixtureAttributeTest.SetUpMethod.TestMethod.TearDownMethod
[success] TestFixtureAttributeTest.SetUpMethod.TestMethod.TearDownMethod
[start] TestFixtureAttributeTest.SetUpMethod.FailedTest.TearDownMethod
[failure] TestFixtureAttributeTest.SetUpMethod.FailedTest.TearDownMethod
TestCase 'TestFixtureAttributeTest.SetUpMethod.FailedTest.TearDownMethod' failed: 
Equal assertion failed.
[[0]]!=[[1]]
MbUnit.Core.Exceptions.NotEqualAssertionException
C:\Documents and Settings\Peli\Mes documents\Tigris\mbunit\src\MbUnit.Core\Framework\Assert.cs(649,0): at MbUnit.Core.Framework.Assert.FailNotEquals(Object expected, Object actual, String format, Object[] args)
C:\Documents and Settings\Peli\Mes documents\Tigris\mbunit\src\MbUnit.Core\Framework\Assert.cs(208,0): at MbUnit.Core.Framework.Assert.AreEqual(Int32 expected, Int32 actual, String format, Object[] args)
C:\Documents and Settings\Peli\Mes documents\Tigris\mbunit\src\MbUnit.Core\Framework\Assert.cs(220,0): at MbUnit.Core.Framework.Assert.AreEqual(Int32 expected, Int32 actual)
c:\documents and settings\peli\mes documents\tigris\mbunit\src\mbunit.tests\testfixtureattributetest.cs(33,0): at MbUnit.Tests.TestFixtureAttributeTest.FailedTest()

1 succeeded, 1 failed, 0 skipped, took 0,00 seconds.


---------------------- Done ----------------------
posted on Sunday, May 09, 2004 11:13:00 PM UTC  #    Comments [3]
 Saturday, May 08, 2004

Drawing a graph, although it sounds intuitive, is a tricky task. It usually involves a number of sophisticated algorithms and even more numerous parameters to set up the layout.

QuickGraph comes with a Managed C++ wrapper of Graphviz, a famous graph drawing library from AT&T. In this blog, I will show how to draw a graph in a few lines.

Let's build a dependency graph between some good old C files:

// create a new adjacency graph
AdjacencyGraph g = new AdjacencyGraph(false);
// adding files and storing names
IVertex boz_h = g.AddVertex(); 
IVertex zag_cpp = g.AddVertex(); 
IVertex yow_h = g.AddVertex();
...

// adding dependencies
g.AddEdge(dax_h, foo_cpp); 
g.AddEdge(dax_h, bar_cpp); 
...

At this point, the graph structure is built and ready to be drawed by graphviz. You need to create an instance of QuickGraph.Algorithms.Graphviz.GraphvizAlgorithm and call it's write method:

// creating graphviz algorithm
GraphvizAlgorithm gw = new GraphvizAlgorithm(
    g, // graph to draw
    ".", // output file path
    GraphvizImageType.Png // output file type
    );
// outputing to graph.
gw.Write("filedependency");

And the result is:

That's not so bad but we would like to see the names of the files. First thing to do, is to tell QuickGraph to produce NamedVertex vertices instead of Vertex. This is done by feeding the AdjacencyGraph constructor with two class factories, one for the vertices, one for the edges:

AdjacencyGraph g = new AdjacencyGraph(
    new NamedVertexProvider(),
    new EdgeVertexProvider(),
    false);

The NamedVertex class a Name property that we can use to store the name of the file:

// adding files and storing names
NamedVertex boz_h = (NamedVertex)g.AddVertex();     boz_h.Name = "boz.h"; 
NamedVertex zag_cpp = (NamedVertex)g.AddVertex();   zag_cpp.Name = "zag.cpp";
NamedVertex yow_h = (NamedVertex)g.AddVertex();     yow_h.Name = "yow.h";

The last step is add attach an event handler to the event of GraphvizAlgorithm that renders the vertices and add the name property:

// outputing graph to png
GraphvizAlgorithm gw = new GraphvizAlgorithm(
    g, // graph to draw
    ".", // output file path
    GraphvizImageType.Png // output file type
    );
gw.FormatVertex +=new FormatVertexEventHandler(gw_FormatVertex);
gw.Write("filedependency");
}
private void gw_FormatVertex(object sender, FormatVertexEventArgs e)
{
    NamedVertex v = (NamedVertex)e.Vertex;
    e.VertexFormatter.Label = v.Name;
}

and now the result is much better:

posted on Saturday, May 08, 2004 10:10:00 AM UTC  #    Comments [2]
 Friday, May 07, 2004

Let's have some fun with graph theory. Today, I'm showing how to generate a random maze with Quickgraph. Before going into the code, let see how we are going to make it.

The maths

Consider that you have a regular lattice like in the image below. If you consider each edge as a path, the lattice represents a highly connected network. The question is: which edge should you delete to make it a maze ?

The answer to this questions is trivial in terms of graph theory: you just need to extract a tree out of the graph and this will be a maze.  In fact in a tree, there is only 1 way from the root to each of the leaf, like in mazes. This leaves us with the problem of extracting a tree from a graph.

The maze generation example was originaly brought up by David Wilson (a researcher from Microsoft). He has designed an efficient algorithm, known as Cycle-Popping Tree Generator, for extracting random tree out of graphs. This algorithm is implemented in QuickGraph so we have all the tools on our hand to start solving the problem.

The code

Let's start by building the graph and the lattice. For the cycle popping algorithm, we need a BidirectionalGraph (a graph where you can iterate the out-edges and the in-edges of the vertices). For the lattice, we create a two dimensional array of vertices and finally, we store the vertex -> lattice index relation into a Hashtable:

// We need a few namespaces for QuickGraph 
using QuickGraph.Concepts;
using QuickGraph.Concepts.Traversals;
using QuickGraph.Algorithms.RandomWalks;
using QuickGraph;
using QuickGraph.Providers;
using QuickGraph.Collections;
using QuickGraph.Representations;

public class MazeGenerator
{
    // the bidirecitonal graph
    private BidirectionalGraph graph = null;
    // 2D array of vertices
    private IVertex[,] latice;
    // v -> (i,j)
    private Hashtable vertexIndices = null;

Next, we write the method that will populate the graph. If the lattice has m rows and n columns, the method will create m*n vertices and (m-1)*(n-1)*2 edges to link those vertices:

public void GenerateGraph(int rows, int columns)
{
    this.latice=new IVertex[rows,columns];
    this.vertexIndices = new Hashtable();
    this.graph = new BidirectionalGraph(false); // false = does not allow parallel edges

    // adding vertices
    for(int i=0;icolumns;++j)
        {
            IVertex v =this.graph.AddVertex();
            this.latice[i,j] = v;
            this.vertexIndices[v]=new DictionaryEntry(i,j);
        }
    }

    // adding edges
    for(int i =0;icolumns-1;++j)
        {
            this.graph.AddEdge(latice[i,j], latice[i,j+1]);
            this.graph.AddEdge(latice[i,j+1], latice[i,j]);
            this.graph.AddEdge(latice[i,j], latice[i+1,j]);
            this.graph.AddEdge(latice[i+1,j], latice[i,j]);
        }
    }
    ...

There is a bit of index gymnastics in the code above, but drawing it on a sheet of paper should make things clear. I will not focus on the drawing code on this blog: I'm using basic features of System.Drawing namespace, nothing really "extreme". So back to our maze problem, we need to apply the cycle-popping algorithm to generate a maze.

Cycle-popping algorithm

The cycle poping algorithm is implement in the QuickGraph.Algorithms.RandomWalks.CyclePoppingRandomTreeAlgorithm class. Using this algorithm is quite straightforward:

// (outi,outj) is the coordinate of the exit vertex in the lattice
// (ini,inj) is the coordinate of the entry vertex in the lattice
public void GenerateWalls(int outi, int outj, int ini, int inj)
{
    // we build the algo and attach it to the graph
    CyclePoppingRandomTreeAlgorithm pop = new CyclePoppingRandomTreeAlgorithm(this.graph);

    // finding the root vertex
    IVertex root = this.latice[outi,outj];
    if (root==null)
        throw new ArgumentException("outi,outj vertex not found");

    // this lines lanches the tree generation 
    pop.RandomTreeWithRoot(root);

At this point, pop contains a dictionary which associates each vertex to it's successor edge in the tree. Remember that the tree is directed towards the root here. This dictionary has two roles: it contains the edges that are part of the maze (that's what we needed) and even better you can build the way-out using the dictionary by following the successors until you hit the root:

    // we add two fields to the class:
    private VertexEdgeDictionary successors = null;
    private EdgeCollection outPath = null;
    ...
    ///////////////////////////////////
    // GenerateMaze continued
    // storing the successors
    this.successors = pop.Successors;

    // build the path to ini, inj
    IVertex v = this.latice[ini,inj];
    if (v==null)
    throw new ArgumentException("ini,inj vertex not found");

    // building the solution path
    this.outPath = new EdgeCollection();
    while (v!=root)
    {
        IEdge e = this.successors[v];
        this.outPath.Add(e);
        v = e.Target;
    }
}

That's it. We can now draw the walls of the maze and draw the solution on top. Thank you Mister Propp and Mister Wilson! (The source of this example is available in the QuickGraph CVS)

posted on Friday, May 07, 2004 11:13:00 PM UTC  #    Comments [8]
 Wednesday, May 05, 2004

MbUnit features a specialized fixture for testing IEnumerable/IEnumerator implementations. This fixtures does a number of test automatically to ensure that the implementation follows the enumerator specification.

In order to use the fixture, you must

  1. Tag your class with EnumerationFixture,
  2. Tag some methods with DataProvider attribute. Those methods will provide data to be added to the collections,
  3. Tag some methods with CopyToProvider attribute. Those methods will copy the data feeded as argument into a collection. The returned collection will be the tested collection.
  4. That's it!

In this example, we use the Data method to provide the data. The enumeration of ArrayList and int[] is tested.

[EnumerationFixture]
public class EnumerationFixtureAttributeAttributeTest
{
    private Random rnd = new Random();
    private int count = 100;
    [DataProvider(typeof(ArrayList))]
    public ArrayList Data()
    {
        ArrayList list = new ArrayList();
        for(int i=0;i<count;++i)
        list.Add(rnd.Next());
        return list;
    }
[CopyToProvider(typeof(ArrayList))] public ArrayList ArrayListProvider(IList source) { ArrayList list = new ArrayList(source); return list; } [CopyToProvider(typeof(int[]))] public int[] IntArrayProvider(IList source) { int[] list = new int[source.Count]; source.CopyTo(list,0); return list; } }
posted on Wednesday, May 05, 2004 9:45:00 PM UTC  #    Comments [1]
 Monday, May 03, 2004

MbUnit comes with several CodeSmith  templates.The AssertWrapper template creates an strongly-typed assertion wrapper using Reflection. This enables the tester to quickly build "specialized" assertion wrapper for his classes.

The template generates an assertion method for each public property of the class. It adapts the name of the way assertion are handled depending on the type of the property. Below, is the wrapper generated for System.Collections.ICollection:

using MbUnit.Core.Framework;
using System.Collections;
namespace MbUnit.Core.Framework
{
 /// <summary>
 /// Assertion helper for the see <cref="ICollection"/> class.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This class contains static helper methods to verify assertions on the
 /// <see cref="ICollection"/> class.
 /// </para>
 /// <para>
 /// This class was automatically generated. Do not edit (or edit the template).
 /// </para>
 /// </remarks>
 public sealed class ICollectionAssert
 {
  #region Private constructor
  private ICollectionAssert
  {}  
  #endregion
  /// <summary>
  /// Verifies that the property value <see cref="ICollection.Count"/>
  /// of <paramref name="expected"/> and <paramref="actual"/> are equal.
  /// </summary>
  /// <param name="expected"/>
  /// Instance containing the expected value.
  /// </param>
  /// <param name="actual"/>
  /// Instance containing the tested value.
  /// </param>
  public static void AreCountEqual(
   ICollection expected,
   ICollection actual
   )
  {
   Assert.IsNotNull(expected);
   Assert.IsNotNull(actual);
   AreCountEqual(expected.Count,actual);
  }
  ...
  
  /// <summary>
  /// Verifies that the property value <see cref="ICollection.IsSynchronized"/>
  /// is true.
  /// </summary>
  /// <param name="actual"/>
  /// Instance containing the expected value.
  /// </param>
  public static void IsSynchronized(
   ICollection actual
   )
  {  
   Assert.IsNotNull(actual);
   Assert.IsTrue(actual.IsSynchronized,
        "Property IsSynchronized is false");
  }
  ...
}
posted on Tuesday, May 04, 2004 2:58:00 AM UTC  #    Comments [1]
 Sunday, May 02, 2004

MbUnit has a decorator that enables you to run you tests against different cultures, i.e. to test that your code is correctly globalized. This is done by taggin the test methods with a MultipleCultureAttribute decorator. This attribute takes a comma separated list of culture names and it will run the test for each of the culture. 

The example below shows how this decorator can test methods that are not correctly globalized.

[TestFixture]
public class MultipleCultureAttributeTest
{
    [Test]
    [ExpectedException(typeof(AssertionException))]
    [MultipleCulture("en-US,de-DE")]
    public void TestConvertFromString()
    {
        string input="2.2";
        double output = double.Parse(input);
        Assert.AreEqual(2.2, output);
    }
    [Test]
    [ExpectedException(typeof(AssertionException))]
    [MultipleCulture("en-US,de-DE")]
    public void TestConvertToString()
    {
        double input = 2.2;
        string output= string.Format("{0}",input);
        Assert.AreEqual("2.2",output); 
    }
}
posted on Monday, May 03, 2004 2:44:00 AM UTC  #    Comments [0]
 Friday, April 30, 2004

Unit Tests and Debug.Assert don't come usually work well together, specially if Debug.Assert pops out a dialog window that stops the execution of tests. MbUnit features a new test decorator that "digests" Debug.Assert calls and "translate" them for MbUnit. Simply tag the test that could trigger Debug.Assert with ExpectedDebugAssertAttribute.

[TestFixture]
public class ExpectedDebugAssertionAttributeTest
{
    [Test]
    [ExpectedDebugAssertion]
    public void ThrowAssertion()
    {
         Debug.Assert(false,"Testing assertion redirection");
     }
}

In the background, the decorator stores the listener in a temporary collection, emptis the Debug.Listeners collection and adds a simple listener that will throw in case of failure. When finishes, Debug.Listeners is rolledback.

The test method ThrowAssertion will fail if we do not trap the exception with ExpectedExceptionAttribute. In fact, in MbUnit, you can chain decorators:

[TestFixture]
public class ExpectedDebugAssertionAttributeTest
{
    [Test]
    [ExpectedException(typeof(AssertionException))] // this will trap the exceptoin
    [ExpectedDebugAssertion] // this will filter Debug.Assert to AssertionException
    public void ThrowAssertion()
    {
         Debug.Assert(false,"Testing assertion redirection");
     }
}

Attention, the order of declaration of decorators is important!

posted on Saturday, May 01, 2004 4:57:00 AM UTC  #    Comments [1]

MbUnit features a new test decorator that asserts that the duration of the test is less than some values. DurationAttribute usage is quite intuitive as shown in the example below:

[TestFixture]
public class DurationAttributeTest
{
    [Test]
    [Duration(1,"This method succeeds (has 1 second to succeed")]
    public void EmptyMethod()
    {}

   [Test]
   [Duration(0,"This method will fail because it will  run in more that 0 seconds!")]
   public void EmptyMethodFails()
   {
      Console.WriteLine("Take your time");
   }
}
posted on Saturday, May 01, 2004 4:47:00 AM UTC  #    Comments [3]

My blog is on (will be soon) the MSDN Belux site :)

http://www.microsoft.com/belux/fr/msdn/community/blogs.mspx

posted on Friday, April 30, 2004 11:58:00 PM UTC  #    Comments [0]

The TypeFixture lets you write a fixture for specific type and apply to a number of instance of this type.This fixture is particularly usefull for writing fixtures of interfaces and apply it to all the types that implement the interface.

In this tutorial, we are going to write a fixture for the IEnumerable interface (note that this interface is best tested with EnumerationFixture).

Fixture logic

The TypeFixture has the following execution logic:

  1. (optional)Set-up the fixture, (SetUpAttribute),
  2. Get an instance of the tested type provided by the user (ProviderAttribute),
  3. Get instances of the tested type provided by a factory (ProviderFactoryAttribute),
  4. Run test method with this instance as argument (TestAttribute)
  5. (optional)Teardown fixture (TearDownAttribute)
Step 1: Creating the fixture

Create a new class EnumerableTest and tag it with TypeFixture. The TypeFixture attribute takes the tested type as parameter:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

[TypeFixture(typeof(IEnumerable))]
public EnumerableFixture
{
}
Step 2:  Create providers

MbUnit needs instance of the tested type to feed them into the different tests. Creating those instances is the job of tester. To do so, you can either

  • write a method in the fixture, tagged with ProviderAttribute that returns an instance of the tested type,
  • give the type of an instance factory that will be used to "produce" new instances
  • or do both appraoch

We start by writing two methods that return respectively and enumerator on a empty list and non-empty list:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

[TypeFixture(typeof(IEnumerable))]
public EnumerableFixture
{
    [Provider(typeof(IEnumerable))]
    public ArrayList ProviderEmptyArrayList()
    {
        return new ArrayList();
    }

    [Provider(typeof(IEnumerable))]
    public ArrayList ProviderArrayList()
    {
        ArrayList list = new ArrayList();
        list.Add(0);
        list.Add(1);
        return list;
    }
}

The disadvantage of "hardcoding" methods in the fixture is that we cannot reuse the code for other fixture, for example, for the IList fixture. To avoid this problem you can wrap you "generation" methods in a class factory and use the ProviderFactory to tell MbUnit to use this factory:

using System;
using System.Collections;
using MbUnit.Core.Framework;
using MbUnit.Framework;

public class ArrayListFactory
{
    public ArrayList Empty
    {
        get
        {
            return new ArrayList();
        }
    }

    public ArrayList TwoElems
    {
        get
        {
            ArrayList list = new ArrayList();
            list.Add(0);
            list.Add(1);
            return list;
        }
    }
}

[TypeFixture(typeof(IEnumerator))]
[ProviderFactory(typeof(ArrayListFactory), typeof(IEnumerable))]
public EnumeratorFixture
{
}

That's much better because we can reuse the factory for other fixtures. Of course, you can attach an arbitrary number of factories and provider methods.

Step 3: Add some tests

Add the unit tests as usuals on the IEnumerable instance. These methods must take the tested type the tested type as argument.

Here we check that the enumerator throws if Current is called while the cursor if before the first element or past the last element:

...
[TypeFixture(typeof(IEnumerable))]
[ProviderFactory(typeof(ArrayListFactory), typeof(IEnumerable))]
public EnumerableFixture
{
    ...

    [Test]
    [ExpectedException(
         typeof(InvalidOperationException),
         "Current called while cursor is before the first element"
    )]
    public void CurrentCalledBeforeMoveNext(IEnumerable en)
    {
          IEnumerable er = en.GetEnumerator(); 
          en.Current;
    }

    [Test]
    [ExpectedException(
         typeof(InvalidOperationException),
         "Current called while cursor is past the last element"
    )]
    public void CurrentCalledBeforeMoveNext(IEnumerable en)
    {
          IEnumerable er = en.GetEnumerator(); 
          while(en.MoveNext());
          en.Current;
    }
}
Step 4: Compile and run

Compile and load in the GUI. MbUnit will scan the providers and create a fixture for each one of them.

posted on Friday, April 30, 2004 9:40:00 PM UTC  #    Comments [4]

This is a step-by-step tutorial to create your first MbUnit test fixture. (Note for NUnit, csUnit user: it is the same syntax).

Step 1: Create and set-up a project
  • Create a library project (assembly) in your favorite .Net language (here it will be C#).
  • Add the following references:
Step 2: Create a TestFixture class

Create a new class MyFirstTest, and tag it with the attribute TestFixture. This will tell  MbUnit that this class contains tests to be executed.

using MbUnit.Core.Framework;
using MbUnit.Framework;

[TestFixture("This is my first test")]
public class MyFirstTest
{
}
Step 3: Add test methods

At this point, MyFirstTest does not have any test. Let's add a method that check that 1+1 = 2. To do so, we add the method OnePlusOneEqualTwo. In the test methods, you can use the assertion checks provided by the Assert static helper class:

[TestFixture("This is my first test")]
public class MyFirstTest
{
    [Test]
    public void OnePlusOneEqualTwo()
    {
         Assert.AreEqual(2, 1+1, "This is an error message");
    }
}

The signature of  OnePlusOneEqualTwo is important, it must be

public void MethodName(void);
Step 4: Running the tests

Once you have compiled the assembly, launch the MbUnit gui. Drag and drop the dll or use context menu to load the test assembly. The tree of available tests should instantly appear on the window. The GUI scans the loaded assembly for types tagged with TestFixture attribute and populates the tree. The namespace are reflected into nodes in the tree.

Hit run to launch the tests. When a test is run succesfully, the background of it's tree icon is turning green, this color propagated to the parents. However, if a test fails, the icon turns red and the parents are also turned red. 

To have informating about a failed test run, click on the node that failed and take a look at the exception. 

posted on Friday, April 30, 2004 8:43:00 PM UTC  #    Comments [12]
 Thursday, April 29, 2004

MbUnit now features several new assertions that touch different aspects of the applications. They provide new tool to easily add complicated assertions into your unit tests. All the new asssertions usually come under two version: the positive and negative "Not" version.

Includsion: Between and In (Assert class)

Two new assertions in Assert: Between and In which behaves as their SQL cousins:

int i=0;
Assert.Between(i, 1, 10);

int[] list = new int{1,2,3};
Assert.In(0, list);

String: StringAssert class

String is a very special type that totally deserves it's own assertions. Using Regular expression (System.Text.RegularExpression.Regex class), we can assert for complicated patterns. For example, checking for SQL injection in a string.

StringAssert.IsNotEmpty("");       // asserts that the string is not empty,
StringAssert.Like("hello", @"\w"); // asserts if it matches a regular expression
StringAssert.FullMatch("12-2344-21",@"\d{2}-\d{4}-\d{2}");// asserts that the match is full

Security: SecuAssert class

Performs some basic security based assertion: check that user is in role, check authentication, etc...

SecuAssert.WindowsIsInAdmin(); // asserts that is in administrator role
SecuAssert.IsAuthenticated(); // asserts that is authenticated
...

Reflection: RefleAssert class

Asserts that types can be assigned to each other, are instance of, or contains desired members:

Type parent;
Type child;

RefleAssert.IsAssignableFrom(parent, child); // asserts that parent is assignable from child
RefleAssert.HasMethod(typeof(String), "Substring", int, int);// asserts that System.String posseses Substring(int, int) method

Performance: PerfAssert class

Provides timing assertions. In the future it might also include memory related assertions:

CountDownTimer cdt = PerfAssert.Duration(10); // asserting that the duration to cdt.Close will last less that 10secs
...
cdt.Stop(); // throws if lastes more that 10 secs.

Data: DataAssert class

Data assertions compare DataSet, DataTable, DataRow and DataColumns content and schema:

DataSet ds;
DataSet ds2;

DataAssert.AreSchemaEqual(ds,ds2); // asserts that schemas of ds, ds2 are equal
DataAssert.AreDataEqual(ds,ds2);   // asserts that data in ds,ds2 are equal
DataAssert.AreEqual(ds,ds2);       // asserts that data and schema of ds,ds2 are equal

DataTable t,t2;
DataAssert(t,t2);

XML assertions: XmlAssert class

Xml comparaison is entirely done by the XmlUnit project from http://xmlunit.sourceforge.net

Formating error message

Assertion that accepts an error message support a "String.Format" like syntax: you can pass a format string and arguments:

string name="Marc";
Assert.AreEqual("John",Marc,"The name {0} does not match {1}", "John",name);

All suggestions for other assertions are welcome...

posted on Friday, April 30, 2004 5:17:00 AM UTC  #    Comments [9]

Consider the problem writing a unit test for the IList.Add method. At first sight this is trivial (as an example, we check that IList.Add supports null reference):

[TypeFixture(typeof(IList))]
public class ListTest
{
   [Test("List accepts null values")]
   public void AddNull(IList list)
   {
       list.Add(null);
       ...
   }
}

Now what about the Readonly and the FixedSize wrapper of ArrayList. They implement IList, but calling IList.Add on them will throw a NotSupportedException. Using the classic ExpectedExceptionAttribute technique, the only solution is to create a special fixture for read-only and fixed size wrappers, and that involves a lot of code duplication.

To tackle this problem, I have added ConditionalExceptionAttribute, which expects an exception if a predicate is true. The predicate is define by a method of the fixture that returns a boolean. This solution is simple and avoids the duplicate of unit tests when possible. Let's addapt the example with the new decorator:

[TypeFixture(typeof(IList))]
public class ListTest
{
   public bool IsReadOnly(IList list)
   {
       return list.ReadOnly;
   }

   [Test("List accepts null values")]
   [ConditionalException(typeof(NotSupportedException),"IsReadOnly")]
   public void AddNull(IList list)
   {
       list.Add(null);
       ...
   }
}

When the test will be executed, if list.ReadOnly is true, the framework will expect to receive a NotSupportedException, but if it is false, he will not check for exception. Note that the parameters of the predicate must match the parameters of the test method and it must return a bool.

posted on Thursday, April 29, 2004 11:35:00 PM UTC  #    Comments [3]
 Wednesday, April 28, 2004

Let's consider a simple fixture with a unit test that must throw. In this case, we use the ExpectedExceptionAttribute to tell the framework that the method should throw:

[TestFixture]
public class MyFixture
{
    [Test]
    [ExpectedException(typeof(Exception))]
    public void ThisMethodThrows()
    { ... }
}

ExpectedExceptionAttrribute is called a Decorator attribute because it decorates and alter the behavior of a test. Another commonly used decorator is IgnoreAttribute to ignore a test.

In MbUnit, other decorators are available. Here I describe two of those: RepeatAttribute and ThreadedRepeatAttribute. RepeatAttribute will make the execution of the test repeated the desired number of times in the same thread while ThreadedRepeatAttribute will launch simultaneously a desired number of threads that will execute the method. RepeatAttribute create a sequence of execution, ThreadedRepeatAttribute create a parallel execution.

    [Test]
    [Repeat(10)] // this will make the RepeatedTest executed 10 times
    public void RepeatedTest()
    { ... }


    [Test]
    [ThreadedRepeat(10)] // this will make the RepeatedTest executed in 10 concurent threads
    public void AmIThreadSake()
    { ... }

Decorators are chained internally in the order that they are defined, therefore declaration order is important if you want to combine them. For example, the two following test methods have different signification:

  • RepeatAndThrow means: repeat test 10 times, test should throw at each execution
  • ThrowWhileRepeating: repeat test 10 times, one of the test should throw during the repetition
    [Test]
    [Repeat(10)]
    [ExpectedException(typeof(Exception))]
    public void RepeatAndThrow()
    { ... }

    [Test]
    [ExpectedException(typeof(Exception))]
    [Repeat(10)]
    public void ThrowWhileRepeating()
    { ... }

posted on Thursday, April 29, 2004 12:51:00 AM UTC  #    Comments [2]
 Tuesday, April 27, 2004

NDoc is an extensible application: you can easily provide your own "documentation renderer", usually called documenter. I have used this feature to integrate NLiterate within NDoc and take advantage the built-in functions of the GUI. Here is the detailled procedure to create the NLiterate documenter.

1) Create the project:

Create an assembly project named NDoc.Documenter.*** where you replace *** with the name of your documenter. It is important to have your assembly named like this otherwise it will not be loaded by NDoc. Add the reference to NDoc.Core.dll.

2) Create the documenter config object:

The config class will be attached to the property grid control in the NDoc gui. This way we can easily define the different parameters of the documenter. The config class must implement IDocumenterConfig interface, however it is easier to inherit from BaseDocumenterConfig:

public class LiterateDocumenterConfig : BaseDocumenterConfig
{
    private string outputFile;
    public LiterateDocumenterConfig()
    :base("Literate")
    {
        this.OutputFile =String.Format(".{0}doc{0}compile-log.txt",Path.DirectorySeparatorChar);
    }

    public string OutputFile
    {
        get
        {
            return this.outputFile;
        }
        set
        {
            this.outputFile = value; 
            this.SetDirty();
        }
    }
}

Note that when OutputFile is modified, we notify NDoc using the protected method SetDirty.

3) Create the documenter class

The documenter class is the main class, it renders the documentation. This class must implement IDocumenter but again, it is easier to use the abstract base class BaseDocumenter:

public class LiterateDocumenter : BaseDocumenter
{ 
    public LiterateDocumenter()
    :base("Literate") // this is the name that will appear in the NDoc list box
    {
        this.Clear();
    }
    #region IDocumenter
    public override void Build(Project project)
    {
        // step one, load snippets
        loadSnippets(project);
        // step two, compile the snippets
        compileSnippets(project);
        // step three, create the report
        compileReport(project);
    }
    public override void Clear()
    {
        this.Config=new LiterateDocumenterConfig();
    }
    public override DocumenterDevelopmentStatus DevelopmentStatus 
    {  
        get
        {
            return DocumenterDevelopmentStatus.Alpha;
        }
    }
    public override string MainOutputFile
    {
        get
        {
            return ((LiterateDocumenterConfig)this.Config).OutputFile;
        }
    }
    #endregion
}

4) Adding progress notification

In the code above, we have not notified NDoc about the progress of the documentation rendering. This can be done through two functions: OnDocBuildingStep and OnDocBuildingProgress. For example:

    public override void Build(Project project)
    {
        // step one, load snippets
        OnDocBuildingStep(0, "Start loading snippets");
        loadSnippets(project);

        // step two, compile the snippets
        OnDocBuildingStep(40, "Start loading snippets");
        compileSnippets(project);
        // step three, create the report
        OnDocBuildingProgress(40); // increasing progress percentage of 40%
        compileReport(project);
    }

5) Copy the assembly

The last step is to copy your assembly into the NDoc bin folder. When launched, NDoc looks for assemblies named "NDoc.Documenter...." and loads by reflection that documenter they are containing. That's it.

posted on Tuesday, April 27, 2004 10:59:00 PM UTC  #    Comments [0]

I have added a new fixture, ProcessTestFixture, that implements the process testing presented by Marc Clifton in http://www.codeproject.com/csharp/autp3.asp.

A process is an ordered sequence of unit tests.  As long as one test passes, the next test is run. Due to the structure of MbUnit, this was straightforward to implement (I'll about this later in the blog). The syntax of the fixture is similar to Marc Clifton example but I have merge Test, Sequence(...) to TestSequence(...):

[ProcessTestFixture]
public MyProcess
{
    [TestSequence(1)]
    public void Hello()
    {...}
    [TestSequence(2)]
    public void World()
    {...}
    ...
}

The implementation of the fixture was done by the following steps:

  1. Create TestSequenceAttribute, a simple class inherited from TestPatternAttribute that stores the order,
    [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
    public sealed class TestSequenceAttribute : TestPatternAttribute
    {
        private int order;
      
        public TestSequenceAttribute(int order)
          {
            this.order = order;
        }
    
        public int Order
        {
            get
            {
                    return this.order;
            }
            set
            {
                this.order = value;
            }
        }
    }
  2. Create ProcessMethodRun, which implements IRun. This is where the "process" logic is created, more specifically in the Reflect method: since this method builds the tree of IRunInvoker instance, creating a process is just a matter of creating a sequence of MethodRunInvoker:
    public class ProcessMethodRun : IRun
    {
        ...
        public virtual void Reflect(
    			        RunInvokerTree tree, 
    			        RunInvokerVertex parent, 
            Type t
        )
        {
            // first gather all methods, with order.
            ArrayList methods = new ArrayList();
            foreach(MethodInfo mi in 
                    TypeHelper.GetAttributedMethods(t,this.AttributeType))
            {
                // get sequence attribute
                TestSequenceAttribute seq = 
                    (TestSequenceAttribute)TypeHelper.GetFirstCustomAttribute(mi,typeof(TestSequenceAttribute)); 
                methods.Add( new OrderedMethod(mi, seq.Order) ); 
            }
    
            // sort the methods
            QuickSorter sorter = new QuickSorter();
            sorter.Sort(methods);
    
            // populate execution tree.
            RunInvokerVertex child = parent;
            foreach(OrderedMethod om in methods)
            {
                IRunInvoker invoker = InstanceInvoker(om.Method);
                child = tree.AddChild(child,invoker);
            } 
        }
    
        protected IRunInvoker InstanceInvoker(MethodInfo mi)
        {
            IRunInvoker invoker = new MethodRunInvoker(this,mi);
            return DecoratorPatternAttribute.DecoreInvoker(mi,invoker);
        }
    
        #region OrderedMethod
        private class OrderedMethod : IComparable
        {
            private MethodInfo method;
            private int order;
       
            public  OrderedMethod(MethodInfo method, int order)
            {
                this.method = method;
                this.order = order;
            }
    
    
            public MethodInfo Method
            {
                get
                {
                    return this.method;
                }
            }
            public int Order
            {
                get
                {
                    return this.order; 
                }
            }
            public int CompareTo(OrderedMethod obj)
            {
                return this.order.CompareTo(obj.order);
            }
       
            int IComparable.CompareTo(Object obj)
            {
                return this.CompareTo((OrderedMethod)obj);
            }
        }
        #endregion
    	}
  3. Create ProcessTestFixtureAttribute, a class that inherits from TestFixturePatternAttribute and defines the fixture execution pipe:
    public class ProcessTestFixtureAttribute : TestFixturePatternAttribute 
    {
        public override IRun GetRun()
        {
            SequenceRun runs = new SequenceRun();
       
            OptionalMethodRun setup = new OptionalMethodRun(typeof(SetUpAttribute),false);
            runs.Runs.Add( setup );
       
            ProcessMethodRun test = new ProcessMethodRun(typeof(TestSequenceAttribute));
            runs.Runs.Add(test);
       
            OptionalMethodRun tearDown = new OptionalMethodRun(typeof(TearDownAttribute),false);
            runs.Runs.Add(tearDown);
       
            return runs;      
        }
    }

Et voilà!

posted on Tuesday, April 27, 2004 7:39:00 PM UTC  #    Comments [2]
 Monday, April 26, 2004

It is very easy to compute the code coverage of the Unit tests using MbUnit and NCover.

  1. Install the latest version of NCover (from gotdotnet: http://www.gotdotnet.com/Community/Workspaces/Workspace.aspx?id=3122ee1a-46e7-48a5-857e-aad6739ef6b9 )
  2. Create a test assembly and compile it in debug mode. NCover needs the symbol files to work (.mdb)
  3. Launch NCover as follows:
    NCover.Console.exe /c "MbUnit.Cons.exe" "MyTestAssembly.dll" /a "TheAssemblyToComputeTheCoverageOn"

    where MyTestAssembly.dll is the unit test assembly, TheAssemblyToComputeTheCoverageOn is the name of the assembly to compute the code coverage on (without the .dll extension)

  4. That' it.
 

You can launch multiple test assembly by providing multiple assembly names. And you can monitor multiple assembly, by providing a ;-separated list of assemblies.

 

posted on Monday, April 26, 2004 9:03:00 AM UTC  #    Comments [6]

I will be presenting MbUnit at the end of May on a BENUG meeting. BENUG stands for Belgian User Group, http://www.benug.be .

posted on Monday, April 26, 2004 8:06:00 AM UTC  #    Comments [4]
 Thursday, April 22, 2004

NDoc is truly an amazing library.

You can easily define your own documentation renderer (Documenter) class by implementing the NDoc.Core.IDocumenter interface (inheriting from BaseDocumenter will help). Once this is done, put the assembly ( named NDoc.Documenter.YourRenderer.dll) into the directory where NDocGUI.exe is and it will be loaded by Reflection where the GUI opens.

Since NLiterate is one way of looking at documentation, it deserved it's own documenter. The task was surprinsgly easy... maybe this could be my 2cents for NDoc :)

posted on Friday, April 23, 2004 4:31:00 AM UTC  #    Comments [1]

I have published a new article on CodeProject about NLiterate ( http://www.codeproject.com/useritems/nliterate.asp )... don't forget to vote :)

 

posted on Thursday, April 22, 2004 11:56:00 PM UTC  #    Comments [0]
 Wednesday, April 21, 2004

Literate programming ( http://www.literateprogramming.com  ) is a way of describing algorithms and programs invented by the the mythical D. Knuth (famous CWEB application). The nice thing about CWEB is that both code and documentation live in the same document. To compile the code, the tool reassembles the code snippets and compiles it. Therefore, you can verify that all the examples in your documentation are compilable. Sadly, the (excellent) C# documentation does not support literate programming... well now it does.

NLiterate is a small application that parses the XML documentation file, reassembles code section and compiles them. This gives you an automated way of testing all your documentation examples. I'll be posting the source soon.

posted on Thursday, April 22, 2004 6:50:00 AM UTC  #    Comments [0]
 Tuesday, April 20, 2004
I have released an article on using XML scripts to pilot SQLpp. Unfortunately, SQLpp is written in C++ and uses template meta-programming which makes compilation time explode. Therefore, the XML script should make it more "user friendly". The full article is at http://www.codeproject.com/useritems/xmlsqlpp.asp
posted on Wednesday, April 21, 2004 1:21:00 AM UTC  #    Comments [0]

I have been wondering if IDataReader was suited for remoting. The answer is obviously no since it derives from IMarshalByRef and therefore, all calls to the interface create a round-trip to the server.

Check out this article for more details.

posted on Tuesday, April 20, 2004 10:47:00 PM UTC  #    Comments [1]
 Sunday, April 18, 2004
This little add-in makes Reflector spit out source code from an entire assembly. Scary and efficient.
posted on Monday, April 19, 2004 2:00:00 AM UTC  #    Comments [0]
This little add-in makes Reflector spit out source code from an entire assembly. Scary and efficient.
posted on Monday, April 19, 2004 2:00:00 AM UTC  #    Comments [1]
 Saturday, April 17, 2004

Consider the simple and tedious task of wrapping C++ classes into Managed C++ (MC++). The classic approach is to make a proxy around an instance of the C++ class allocated on the heap:

// the C++ class
class A {...};

// the MC++ wrapper
public __gc class MA
{
    A* a;
public:
    MA() { a = new A();}
    ~MA() { delete a;}
}

This works well for individual classes (although it is a tedious work) but it fails when it comes to map inherance. Let's add a second class to our example:

class A 
{
public:
    virtual void method();   
};

class B : public A
{
public:
    virtual void method();
}   

The proxies for A,B should map the inherance the original classes, therefore I would expect to have something like this:

public __gc class MB : MA
{
  ???
}
Now, the question is: where should I instanciate B, where should I store the pointer without making ugly casts all over-the-place. The answer is simple: Stop MC++ and wait C++/CLR announced in a near future. 
posted on Saturday, April 17, 2004 9:39:00 PM UTC  #    Comments [0]
 Friday, April 16, 2004

Working on a database application, the urge for testing of database has appeared. Unfortunaltely, there are no real framework that can tackle this problem (real means with specialized assertion and fixtures). Unit test framework like NUnit are too simplistic to provide such functionality.

A little hope: I have run into this nice article which gives an introduction about database testing. The author gives a good methodology to set up a test framework for database:

    1. Separate production database from test database
    2. The test fixture must empty the tables of the test db befure launching the runs 
    3. do small unit tests using the business objects.

 There is one big gotcha about this: usually database are run in an "heavy" multithreaded environment and, in testing, we would like to detect locks and so on. The Unit test approach is too gentle :). I'll come back on this problem later (with somes solutions hopefully).

posted on Saturday, April 17, 2004 3:22:00 AM UTC  #    Comments [2]

NDoc, the best and free documentation compiler for C# has lately released v1.3. This version adds a very interresting new feature: custom tags.Basically, you just need to provide the XSLT templates to NDoc and it use them to render you tags: simple, efficient and highly customizable.

In the NCollection project, we needed a way to easily document the complexity of methods (average and worst). A custom tag was the perfect solution for that: (hint: I'm using brackts intead of minus/greater)

/// [complexity worst="n" average="1" /]
public void Method()
{...}

Starting from the NDoc example, the XSLT stylesheet to render this tag is:

[xsl:template mode="remarks-section" match="complexity">
[H4 class=dtH4>Complexity[/H4]
    [UL]
        [LI]Average: O([xsl:value-of select="@average"][/xsl:value-of])
        [LI]Worst-case: O([xsl:value-of select="@worst"])[/LI]
    [/UL]
    [xsl:apply-templates select="*"/]
[/xsl:template]

Et voilà!

posted on Saturday, April 17, 2004 2:34:00 AM UTC  #    Comments [1]
 Thursday, April 15, 2004

I have upgraded my WikWikiWeb module for DotNetNuke 2.0 along with some new features:

  • RSS feads,
  • Email notifications,
  • Some bug improbements.

Download is available at www.dotnetwiki.org .

posted on Friday, April 16, 2004 6:45:00 AM UTC  #    Comments [1]

CodeSmith is a well-known freeware code generator that I highly recommend to any developper, no matter the language.

I will be using CodeSmith to create templates for strongly-typed AdjacencyGraph classes of QuickGraph.

posted on Friday, April 16, 2004 6:11:00 AM UTC  #    Comments [0]

Highly promising refactoring project featuring

  • code instrumentation,
  • type substitution,
  • method prologue/epilogue decoration,
  • etc...

More at http://rail.dei.uc.pt/

posted on Friday, April 16, 2004 5:59:00 AM UTC  #    Comments [1]
This is my first test entry.
posted on Thursday, April 15, 2004 11:27:00 PM UTC  #    Comments [0]