Friday, August 27, 2004

TestFu has now limited support for generate test suites using Combinatorial Testing as the TestFu.Operations namespace. Combinatorial Testing is an interresting testing technique that has been studied a quite some time now (see citeseer search). There already exists a few package that provide tools to generate test suites (see jenny, allpairs) but none in the .Net framework.

Combinatorial Testing description and Glossary

In this chapter, I will define the different "actors" that interact in the combinatorial testing. I will link them to their corresponding interface in TestFu.

  • A domain (IDomain) is a finite set of objects.
    • Ex: {1,2,3} is a domain composed of the integers 1,2,3
  • The boundary of a domain D is the set of objects in D that are at the boundary of the domain.  The boundary is also a domain,
    • If we decide that the first and last element of an array is it's domain, {1,3} is the boundary of {1;2,3}
  • A tuple (ITuple) acts as a container for other objects,
  • A product on a domain collection (IDomainCollection) is an algorithm (ITupleEnumerable) that generate a suite of tuples (ITupleEnumerator), created by combining one element of each domain, using a predefined strategy.

Currently, the only product available is the cartesian product which returns an exhaustive enumeration of the all possible combination. It is well-known that this product is not efficient at all covering the tests because of the exponential explosion of the number of suites, better strategy have been developped such as the PairWaise covering (all pairs), t-wize, etc... I haven't had the time to look at those yet.

Let's see some code

The TestFu.Operations namespace is designed to be simpler but no simpler. Let's start by defining some domains:

int[] array1 = { 1, 2 };
string[] array2 = { "a", "combinatorial", "hello", "world" };
char[] array3 = { 'a', 'b', 'c' };

Note: TestFu.Operations currently supports arrays, collection (ICollection), enumerable collection (IEnumerable) or singleton domain (1 element). Of course, this is totally extendible. You could easily think about a domain reading the rows of a DataTable, or the elements of a XmlDocument

The static class Products contains a rich set of methods that can create the different products. Let's start with the cartesian product of array1 x array2:

int i = 1;
foreach (ITuple tuple in Products.Cartesian(array1, array2))
{
    Console.WriteLine("\t{0}: {1}",i++,tuple);
}

-- output
        1: 1, a
        2: 1, combinatorial
        3: 1, hello
        4: 1, world
        5: 2, a
        6: 2, combinatorial
        7: 2, hello
        8: 2, world

As expected, each returned tuple is a collection of element from each domain. We could also decide to test the boundaries of the arrays only (first and last element each time):

i = 1;
foreach (ITuple tuple in Products.BoundaryCartesian(array1, array2))
{
    Console.WriteLine("\t{0}: {1}", i++, tuple);
}

-- output
        1: 1, a
        2: 1, world
        3: 2, a
        4: 2, world

The products can act on an arbitrary number of domains so we can add array3 in the product (don't forget about the explosion of the tests number!):

i = 1;
foreach (ITuple tuple in Products.Cartesian(array1, array2, array3))
{
    Console.WriteLine("\t{0}: {1}", i++, tuple);
}

-- output
        1: 1, a, a
        2: 1, a, b
        3: 1, a, c
        4: 1, combinatorial, a
        5: 1, combinatorial, b
        6: 1, combinatorial, c
        7: 1, hello, a
        8: 1, hello, b
        9: 1, hello, c
        10: 1, world, a
        11: 1, world, b
        12: 1, world, c
        13: 2, a, a
        14: 2, a, b
        15: 2, a, c
        16: 2, combinatorial, a
        17: 2, combinatorial, b
        18: 2, combinatorial, c
        19: 2, hello, a
        20: 2, hello, b
        21: 2, hello, c
        22: 2, world, a
        23: 2, world, b
        24: 2, world, c

Where to go from here ?

The next important step is to implement an algorithm that computes the pair-wize or t-wize suite generation. This is very important if you have a lot of domains. In a near future, I will also show how we can use these products to produce a new type of fixture in MbUnit. This fixture was suggested by Jamie Cansdale.

In this post, I have showed a new, simple, way of creating combinatorial tests using the TestFu.Operations namespace.

posted on Saturday, August 28, 2004 3:07:00 AM UTC  #    Comments [5]
 Thursday, August 26, 2004

Yesterday, Jamie Cansdale (NunitAddin) and I spent time "pair-programming" on MbUnit, NUnitAddIn and other tools like the Reflector.Graph addins. The collaboration has been very productive! I've got a lot of blog entry to write about the things we have built yesterday, I'll summarize quickly:

  • MbUnit has now a much better support for NUnitAddIn:
    • this solution should be "version" proof: it should not break if NUnitAddIn updates and so on,
    • you can select a method and execute the tests involving that method,
    • MbUnit generates the Html report and puts the URL in the output, ready for you
  • MbUnit has new fixtures! CrossFixture generates generate the cross products of different data source and hands it to the test...
  • Reflector.Graph renders to SVG: we are now hosting IE inside Reflector to display SVD graphs...
  • Reflector.Graph graphs has clickable links! You can click on an assembly to load it, and so on...

A lot of work, a lot of fun...

 

posted on Friday, August 27, 2004 2:27:00 AM UTC  #    Comments [0]
 Tuesday, August 24, 2004

In this entry, I'll give a tutorial on using QuickGraph to compute the maximum flow of a capacitated network. I will start by giving some defnitions in order to make things clear, then I will apply the QuickGraph algorithms to a practical example.

Maximum Flows

Computing the maximum flow in a network is one of the classic graph theory problem (see [1]). Here's a prototype of flow network:

Imagine a pipeline network for transporting oil from a single source to a single sink. Each edge represents a section of pipeline, and the endpoints of the edge corresponds to the junctures at the ends of that section. The edge capacity is the maximum amount of oil that can flow through the corresponding section per unit time.

What is the maximum amount of oil per unit time that can flow through the network ? That question is a maximum flow problem.

A single-source single-sink network is a connected directed graph that has a distinguised vertex called the source with nonzero outdegree, and a distinguished vertex called sink with  nonzero indegree. A single source-single sink network with source s and sink t (also called target) is called a s-t network. A capacitated network is a connected directed graph such that each edge e is assigned a nonnegative weight cap(e), called the capacity of edge e.

In the following, we shall consider a capacitated s-t network.

Sample network

I will illustrate the example on a 5-vertex capacitated network with source s and sink t as depicted below. This network is extracted from Chapter 12 of [1].

By convention, each edge is tagged with it's capacity (on the left) and, if computed, the flow. s is the source, t is the sink.

Building the sample network with QuickGraph

The first step of the tutorial is to create the sample network above using QuickGraph. To do so, we create a AdjacencyGraph and populate it "manually" with the vertices and edges:

using QuickGraph; // NamedVertex
using QuickGraph.Providers; // providers
using QuickGraph.Representations; // AdjacencyGraphg
using QuickGraph.Concepts; // IEdge

// the graph
AdjacencyGraph graph = new AdjacencyGraph(
    new NamedVertexProvider(),
    new EdgeProvider(),
    true);
// the capacity dictionary
EdgeDoubleDictionary capacities = new EdgeDoubleDictionary();

// adding vertices
NamedVertex s = (NamedVertex)graph.AddVertex(); s.Name = "s";
NamedVertex x = (NamedVertex)graph.AddVertex(); x.Name = "x";
NamedVertex v = (NamedVertex)graph.AddVertex(); v.Name = "v";
NamedVertex w = (NamedVertex)graph.AddVertex(); w.Name = "w";
NamedVertex t = (NamedVertex)graph.AddVertex(); t.Name = "t";

// adding edges
IEdge sx = graph.AddEdge(s, x); capacities[sx] = 5;
IEdge sv = graph.AddEdge(s, v); capacities[sv] = 7;
IEdge xv = graph.AddEdge(x, v); capacities[xv] = 3;
IEdge xw = graph.AddEdge(x, w); capacities[xw] = 7;
IEdge wv = graph.AddEdge(w, v); capacities[wv] = 5;
IEdge wt = graph.AddEdge(w, t); capacities[wt] = 4;
IEdge vt = graph.AddEdge(v, t); capacities[vt] = 6;

Once the graph is built, you can easily draw it using GraphvizAlgorithm. This topic has already been discribed in previous posts so I won't enter into the details .

Preparing the network for the Maximum Flow

In order to work properly, the maximum flow algorithms require that for each edge (u,v) in the network, there exists a reversed edge (v,u). Moreover, a dictionary associating each edge to its reversed must be provided. The sample network obviously does not fullfill this requirement. Therefore, we must add "articifial" reversed edge that have capacity equal to zero. In order to help you with this (tedious) task, QuickGraph provides the ReversedEdgeAugmentorAlgorithm algorithm that will do the job for you:

using QuickGraph.Algorithms.MaximumFlow;

// creating the augmentor
ReversedEdgeAugmentorAlgorithm reversedEdgeAugmentor = new ReversedEdgeAugmentorAlgorithm(this.graph);
// attaching handler to the ReversedEdgeAdded event
// this event is triggered on each "artifical" edge added to the graph
ReversedEdgeAugmentorAlgorithm reversedEdgeAugmentor.ReversedEdgeAdded += new EdgeEventHandler(reversedEdgeAugmentor_ReversedEdgeAdded);

// add the articifial edges
reversedEdgeAugmentor.AddReversedEdges();
...
// cleans up
reversedEdgeAugmentor.RemoveReversedEdges();

// this handler sets the capacity of the new edge to zero
void reversedEdgeAugmentor_ReversedEdgeAdded(Object sender, EdgeEventArgs e)
{
    capacities[e.Edge] = 0;
}

The method AddReversedEdges augments the graph with the reversed edges, while the RemoveReversedEdges "cleans up the mess". If we draw the flow graph after the AddReversedEdges call, it gives the following results (where the reversed edges are dashed):

Computing the MaximumFlow

QuickGraph implements 2 maximum flow algorithms: Edmund Karp and Push Relabel. We will use PushRelabel as it is more efficient, however, both inherit from the abstract base class MaximumFlowAlgorithm. The method Compute computes the maximum flow and returns it's value:

MaximumFlowAlgorithm algo = new PushRelabelMaximumFlowAlgorithm(
    graph,
    capacities,
    reversedEdgeAugmentor.ReversedEdges
    );

double value = algo.Compute(s, t);

After cleaning up the reversed edges, we can draw the graph with the maximum flow in each edge. Note that for this sample, the maxium flow value is 10.

Demo source

The full source of the demo is available in the MbUnit CVS at http://mbunit.tigris.org/source/browse/mbunit/src/QuickGraphTest/MaximumFlowDemo.cs

Acknoledgment

Many thanks to Arun Bhalla for porting PushRelabel to C#

References

[1] Graph Theory and Its applications, Jonathan Gross and Jay Yellen

posted on Tuesday, August 24, 2004 11:02:00 PM UTC  #    Comments [7]
 Monday, August 23, 2004

As mentionned in a previous post, I mentionned that dnAnalytics was a new project providing a managed wrapper above LAPACK. Those guys have been doing a great job and the current release (trunk 271) is already featuring a lot of the "classic" Matrix Algebra algorithms:

  • Dense matrices (float or double) with support for the classic operations, +, *, -,
  • Norms: norm-1, norm-2, norm-infty, etc...,
  • Condition number,
  • QR decomposition,
  • LU decomposition,
  • SVD decomposition

The library is both accessible as a fully managed version, and a managed wrapper above the native, rock solid, LAPACK library. If you are doing matrix algebra in your application, and you care about robustness, efficiency and accuracy, you should be interrested by this project.

 

posted on Tuesday, August 24, 2004 1:22:00 AM UTC  #    Comments [0]
 Sunday, August 22, 2004

In my previous Singleton Unit Testing, I proposed a possible solution for unit testing a singleton (I'll name it the ShortLivingSingleton approach). Omer Van Kloeten came up with another approach (the KillTheSingleton approach), Darren Oakey with the CreateForTesting approach and , Len Holgate finishes the picture tearing appart our the first 2 solutions (the SingletonIsBad approach). Since comments on this topic have been interresting, they are worth a little summary.

The problem

The application you are developping is using a Singleton, that you need to test. How do you test a singleton ?

SingletonIsBad approach

  1. Singleton are evil! If you have the opportunity to refactory the code, make sure you definitely need this singleton, otherwize get rid of it.
  2. You have no choice and you cannot get rid of the singleton. Make sure you split the singleton functionalities in two classes: The class that does all the work and the singleton aspect that prevents multiple instances. Doing so, you will not have to cheat to test the singleton.
  3. You could not fullfill any of the point above, and you will need to cheat...

The two first point came from Len Holgate and I totally agree with him. The third point is for tester who do not have the possiblity of avoiding or refactoring the singleton. To tackle this problem, I and Omer have proposed 2 cheats and Darrel Oakley proposed a wider solution to the problem.

CreateForTesting approach

The approach asks you to embed some functionality in a class that helps other people test it. The most common thing is to add - to most objects - a function CreateTestFoo, where Foo is the object that you are testing. This gives you a new and fully initialized version of Foo - however complicated Fooactually is.

Cheating the singleton.

Both cheat solutions are based on Reflection, therefore they will not work if you have denied Reflection on your tested assembly (Haacked's  comment).

ShortLivingSingleton  approach

This approach consists of creating a new non-singleton approach for each test and do the testing on this instance. To do so, we use reflection to access the private constructor and instanciate the singleton. Therefore, the singleton is never created and never used.

KillTheSingleton approach

This approach kills the singleton after each test, in the TearDown method for example. To "kill" the singleton, the static field holding the singleton reference is nullified using Reflection and garbage collection is forced.

Conclusions

Singletons are evil but yet you find people using them (shame on me). They are problematic to test because you cannot separate the unit tests.  The first step for testing them is actually to refactor your application and get rid of the singleton. If this cannot be done, you have to cheat the singleton using Reflection to properly test them.

ps: I'd like to thank all the people who commented the blog entry for their constructive comments :) Cheers, Jonathan

posted on Monday, August 23, 2004 1:06:00 AM UTC  #    Comments [6]
 Thursday, August 19, 2004

Here are the NSort benchmarks for arrays of integer filled with random data. These benchmarks are for the non-generic versions.

The code to generate the benchmarks uses NPerf is given below:

using System;
using System.Collections;
using NPerf.Framework;

namespace NSort.Perf
{
    [PerfTester(typeof(ISorter), 10
        , Description = "Sort Algorithm benchmark for Random data"
        , FeatureDescription = "Collection size")]
    public class SorterBenchmark
    {
        protected int[] list;
        public int CollectionCount(int testIndex)
        {
            int n = 0;
            if (testIndex < 0)
                n=10;
            else
                n = (testIndex+1)*500;
            return n; 
        }
        [PerfRunDescriptor]
        public double RunDescription(int testIndex)
        {
            return (double)CollectionCount(testIndex);
        }

        [PerfSetUp]
        public override void SetUp(int testIndex, ISorter sorter)
        {
            Random rnd = new Random();
            this.list = new int[CollectionCount(testIndex)];
            for (int i = 0; i < this.list.Length; ++i)
                this.list[i] = rnd.Next();
        }
        [PerfTest]
        public void SortRandomData(ISorter sorter)
        {
            sorter.Sort(this.list);
        }
    }
}

 

posted on Thursday, August 19, 2004 11:48:00 PM UTC  #    Comments [0]
 Wednesday, August 18, 2004

NSort is a very nice and flexible package of sorting (15) algorithms from which the developer can choose. This library was a jointly work from me, Marc Clifton and Robert Rohde. In this blog, I'll show how NSort can be quickly "upgraded" to Generic and how you can use the extensibility of MbUnit to test it efficiently.

Generic

Converting the algorithms to Generic was really straightforward. For almost all cases, it was just a matter of adding <T> here and there, and replacing temporary object instance by T. Let's see this with the two interfaces of the project: IStorter and ISwap:

using System.Collections;
...

public interface ISorter
{
    IComparer Comparer {get;}
    void Sort(IList list);
}
public interface ISwap
{
    void Swap(IList array, int left, int right);
    void Set(IList array, int left, int right);
    void Set(IList array, int left, object obj);
}

Now, their generic brothers:

using System.Collections.Generic;
...

public interface ISorter<T>
{
    IComparer<T> Comparer {get;}
    void Sort(IList<T> list);
}
public interface ISwap<T>
{
    void Swap(IList<T> array, int left, int right);
    void Set(IList<T> array, int left, int right);
    void Set(IList<T> array, int left, object obj);
}

That was pretty quick. The conversion of the algorithms followed the same ideas and a dozens of cut/paste/replace later the NSort.Generic namespace was born.

Testing

There is a well-know proverb that says "the one who live by the cut-and-paste, die by the cut-and-paste" and that's exactly how I ported NSort to generics... so to ensure the quality of it really needs proper testing.

Testing NSort

Let's start with the testing of the non-generic classes. The main purpose of the NSort is to provide implementation of the ISorter interface that effectively sort list of elements and that's what we are willing to test. A quick (internal) brain strom for test cases of ISorter yields:

  • Sort a null list throws ArgumentNullException,
  • Sort a list with 0,1,2, n (n large) elements check it is effectively sorted. The purpse of the 0,1,2 is to test "boundary" lists.

Since we are testing an interface, this is a good candidate to use CompositeUnitTesting the TypeFixture of MbUnit:

[TypeFixture(typeof(ISorter))]
public class SorterTest
{
    private int[] list;
    private void CreateSortAndCheckSorted(ISorter sorter, int length)
    {
        Random rnd = new Random();
        list = new int[length];
        // create data
        for (int i = 0; i < list.Length; ++i)
            list[i] = rnd.Next();

        // sort table
        sorter.Sort(list);

        // verify
        for (int i = 0; i < list.Length - 1; ++i)
        {
            Assert.IsTrue(sorter.Comparer.Compare(list[i], list[i + 1]) <= 0,
                "Element {0} ({1}) is strictly greather that {1} ({2})",
                i, list[i], i + 1, list[i + 1]
            );
        }
    }

    [Test]
    [ExpectedArgumentNullException]
    public void SortNulList(ISorter sorter)
    {
        sorter.Sort(null);
    }

    [Test]
    public void SortEmptyList(ISorter sorter)
    {
        CreateSortAndCheckSorted(sorter, 0);
    }
    [Test]
    public void SortListWithOneElement(ISorter sorter)
    {
        CreateSortAndCheckSorted(sorter, 1);
    }
    [Test]
    public void SortListWithTwoElements(ISorter sorter)
    {
        CreateSortAndCheckSorted(sorter, 2);
    }
    [Test]
    public void SortListOfSize100(ISorter sorter)
    {
        CreateSortAndCheckSorted(sorter, 100);
    }
}

Now that we have defined the fixture, we need to feed it with ISorter instances. Usually, you would need to write a factory class that would create the instance, but this task was too boring not to be automated. What I want is a way to tell MbUnit to look for all the classes in NProf that implemented ISorter that apply the fixture to it...

Implementing a custom factory attribute:

The TypeFixture fixture looks for attributes that derive from ProviderFixtureDecoratorPatternAttribute and invoke their GetRun method to gather the IRun instance. Therefore, we "just" need to inherit from this attribute and implement the behavior we want:

[AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =true)]
public class AssemblyProviderFactoryAttribute : ProviderFixtureDecoratorPatternAttribute
{
    private Type assemblyType; // type contained in the assembly to test
    private Type targetType; // the tested type
    public AssemblyProviderFactoryAttribute(Type assemblyType, Type targetType)
    {
        ...
        this.assemblyType = assemblyType;
        this.targetType = targetType;
    }
    public Assembly Assembly
    {
        get { return this.assemblyType.Assembly;}
    }
    public Type TargetType
    {
    get { return this.targetType;}
    }
    public override IRun GetRun(Type decoratedType)
    {
        throw new NotImplementedException();
    }
}

The GetRun still needs to be implemented. The task for the returned Run object is to explore the tested Assembly (assemblyType.Assembly) for types  compatible with targetType. MbUnit provides an abstract base class, Run, for implementing IRun:

public class AssemblyProviderRun : Run
{
    private AssemblyProviderFactoryAttribute attribute;
    public AssemblyProviderRun(AssemblyProviderFactoryAttribute attribute)
    {
        this.attribute = attribute;
    }

    public override void Reflect(RunInvokerTree tree, RunInvokerVertex parent, Type t)
    {
        foreach (Type type in this.attribute.Assembly.GetExportedTypes())
        {
            if (!type.IsClass) // interrested in class only,
                continue;
            if (type.IsAbstract) // abstract class cannot be created
                continue;
            if (!this.attribute.TargetType.IsAssignableFrom(type)) // must be assignable to TargetType
                continue;
            // trying to get the default constructor
            ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
            if (ci == null)// no default constructor
                continue;

            ActivatorRunInvoker invoker = new ActivatorRunInvoker(this, type);
            tree.AddChild(parent, invoker);
        }
    }
}

ActivatorRunInvoker is a IRunInvoker implementation that takes a type, creates an new instance of it and feeds it to the arguments of the next invoker. We implement this invoker by inheriting from the abstract base class RunInvoker:

public class ActivatorRunInvoker : RunInvoker
{
   private Type targetType;
   public ActivatorRunInvoker(IRun run, Type targetType)
   :base(run)
   {
      this.targetType = targetType;
   }
   public override string Name
   {
   get {return this.targetType.Name;}
   }
   public override object Execute(object o, System.Collections.IList args)
   {
      Object target = Activator.CreateInstance(targetType);
      args.Add(target);
      return null;
   }
}

That's the end of the journey. The attribute is ready to be used to tag the SorterTest fixture:

[TypeFixture(typeof(ISorter))]
[AssemblyProviderFactory(typeof(ISorter),typeof(ISorter))]
public class SorterTest
{
   ...
}

Let's launch those test and see what happens. I like having my Test assemblies "self-executable" so I make it a Console application and the AutorRunner in the Main method. The Text report spits out:

Tests run: 75, Failures: 0, Not run: 0

This makes sense because there are 15 ISorter implementation times 5 tests applied to them. Of course, I would like to have more information, so I generate the Html report:

Here we see clearly which class is being tested and so, our new attribute is working perfectly without recompiling MbUnit!

Testing NSort.Generics

In order to test the generic sort algorithm, we need to take the following steps:

  1. adapt the SorterTest fixture for the ISorter<int> interface (I choose to test int only),
  2. adapt the AssemblyProviderRun to support generics

The task 1 is trivial and is similar to the ISorter to ISorter<T> transformation. The second task is more technical because we need to check that types are generic and handle them differently. To cut the story short, here is the method that iterates over generic types:

private void ReflectGenericTypes(RunInvokerTree tree, RunInvokerVertex parent)
{
    Type[] args = this.attribute.TargetType.GetGenericArguments();
    foreach (Type type in this.attribute.Assembly.GetExportedTypes())
    {
        if (!type.IsClass)
            continue;
        if (type.IsAbstract)
            continue;
        if (!type.HasGenericArguments) // true if type is a generic
            continue;

        // get the generic type definition
        Type genericType = type.GetGenericTypeDefinition();
        // bind types
        Type gtype = genericType.BindGenericParameters(args);
        // check if assignable
        if (!this.attribute.TargetType.IsAssignableFrom(gtype))
            continue;
        // create new invoker
        AddInvoker(tree, parent, gtype);
    }
}

It took me a while to fix that up but I finally got though. Now, the GenericSorterTest looked as follows and I was ready to hit the "Run" button:

[TypeFixture(typeof(ISorter<int>))]
[AssemblyProviderFactory(typeof(ISorter), typeof(ISorter<int>))]
public class GenericSorterTest
{...

The text report of the tests returned 150 tests, which was logical and they all passed (after some bug fixing). And I'm happy.

The method of testing I showed here worked well because of the nature of the problem to test: the ISorter class are all well separated and do not need mocking and so on.  One of the nicest thing about this is that if you write new ISorter implementations, you do not need to modify your fixutre, they will be automatically tested by MbUnit.

 

posted on Thursday, August 19, 2004 12:27:00 AM UTC  #    Comments [0]

The date finally came through. I will present a workshop on testing on September 9 for the BENUG (Benelux .Net User Group) association on Testing. This will be a "exercise" oriented workshop.

posted on Wednesday, August 18, 2004 9:13:00 AM UTC  #    Comments [6]
 Tuesday, August 17, 2004

Eric Gunnerson has recently blog about a Trebuchet (that he offered to his wife?). This remembered me of the one I built, with my friends, a few years ago.

The photo below shows the "implementation" of the Trebuchet and some facts about it:

  • the rotating pole was 7m long and composed of two wooden poles of 15cm of diameter
  • the rotation axis was made of a steel stick of 26mm of diameter. It was at 3.5 m of the ground. Note because the construction was not perfectly symmetric, it got twisted.
  • the "counter"-weight was about 100kg altough not measured,
  • the structure was composed of 10 wooden poles buried 50cm into ground.
  • the projectile was a piece of wood, 50cm long, 15cm diameter, it got throwed at around 60 meter althought the trajectory was far from behing optimal (too vertical).

posted on Wednesday, August 18, 2004 12:55:00 AM UTC  #    Comments [4]

At first sight it may seem that Singleton and Unit Testing are not compatible since you cannot ensure the separation between the tests. We could solve the problem by instanciating a new "Singleton" instance for each test and apply test on this "local" instance. The problem is that a well implemented Singleton is sealed and it's constructor are private (see Singleton Pattern here) and thus you cannot create this instance.

using System;

public sealed class Singleton
{
   ...
   private Singleton() {}

   public static Singleton Instance
   {
      get { ...}
   }
}

Reflection to the rescue

An elegant way for bypassing the "creation problem" is to use Reflection to get the private constructor (ConstructorInfo) and then use this constructor info to create a new "Singleton" instance.

using System.Reflection;

[TestFixture]
public class SingletonTest
{
    private Singleton target = null;
    [SetUp]
    public void SetUp()
    {
        ConstructorInfo ci =
            typeof(Singleton).GetConstructor(
                BindingFlags.Instance |
                BindingFlags.NonPublic,
                null,
                Type.EmptyTypes,
                null
                );
         Assert.IsNotNull(ci);
         this.target = (Singleton)ci.Invoke(null);
    }
}

Now we have a new instance of the Singleton for each test and we are happy.

posted on Wednesday, August 18, 2004 12:14:00 AM UTC  #    Comments [18]
 Friday, August 13, 2004

Jamie Cansdale has found a hidden gem in .Net 2.0: the much awaited InternalsVisibleTo attribute. This attribute let's you specify the name of an assembly that can view the internals... That's perfect for testing internal classes.

http://weblogs.asp.net/nunitaddin/archive/2004/08/13/214130.aspx

posted on Saturday, August 14, 2004 3:51:00 AM UTC  #    Comments [2]

QuickGraph now contains a condensation graph and transitive closure algorithm which were ported from the BGL by Rohit Gadogkar. Here's a recap. of the definitions of those type of graphs (takened from the Boost Graph Library reference)

A condensation graph is a a graph CG=(CV,CE) based on the graph G=(V,E) where each vertex in CV corresponds to a strongly connected component in G and edge (u,v) is in CE if and only if there exists an edge in E connecting any of the vertices in the component of u to any of the vertices in the component of v.

The transitive closure of a graph G = (V,E) is a graph TG = (V,TE) such that TE contains an edge (u,v) if and only if G contains a path (of at least one edge) from u to v.

Condenstation Graph

Assume that you have built a graph g using QuickGraph:

IVertexListGraph g = ...;

The algorithm responsible for the condensation graph creation is QuickGraph.Algorithms.CondensationGraphAlgorithm and takes the graph to condensate as parameter:

CondensationGraphAlgorithm condensator = new CondensationGraphAlgorithm(g);

In order to compute the condensation, we need to provide a mutable graph, for example a AdjacencyGraph, and call the Create method:

AdjacencyGraph cg = new AdjacencyGraph(true);
condensator.Create(cg);

At this moment, cg contains the condensation graph of g. The only problem here, is that we have not stored the information about which vertex from V was associated to a vertex in CV. In order to do that, we need to add some event handlers to the algorithm. 

This algorithm defines one event, InitCondensationGraphVertex, which is trigerred for each new vertex of the condenstation graph CG. Remember that this vertex (in CV) "contains" all the vertices of a component in the original graph. In this example, we will create a condensation graph that creates NamedVertex, which has the Name property, and we concatenate the names of the condensed vertices to make it the name of the condensated vertex:

// using NamedVertexProvider in order 
// to create NamedVertex instances
AdjacencyGraph cg = new AdjacencyGraph(
    new NamedVertexProvider(),
    new EdgeProvider(),
    true);

// attaching event handler
condensation.InitCondensationGraphVertex+=
    new CondensationGraphVertexEventHandler(condensator_InitCondensationGraphVertex);
// computing
condensator.Create(cg);

...
// Event handler
void condensation_InitCondensationGraphVertex(
    object sender, 
    CondensationGraphVertexEventArgs arg)
{
    NamedVertex cv = (NamedVertex)arg.CondensationGraphVertex;
    
    StringWriter sw = new StringWriter();
    foreach (IVertex v in arg.StronglyConnectedVertices)
    {
        sw.Write("{0}\\n", v);
    }
    v.Name = sw.ToString();
}

That's it... Here are two images of graphs. The left image shows a state graph that is not strongly connected and the right image shows the condensation graph of it.

posted on Saturday, August 14, 2004 12:44:00 AM UTC  #    Comments [0]
 Tuesday, August 10, 2004

Iterators is one of the big, expected, new feature of C# 2.0. It should revolutionize the way you define your collection. Since iteration is fun, people have started to do some interresting and smart things with tem. So I decided, it was time I started playing with them. I'll assume that you have a basic knowledge of the new Generic syntax.

Background: STL algorithms

There was some ancient time where I was still a C++ user. At that time, I was using the Standard Template Library (STL) , a famous C++ library. This library makes an extensive use of template and what is called "generic programming". This library features containers, iterators and algorithms and was the basis of the work I have done in this post.

An introductrory example: filtered enumeration

Let's start with a simple, and yet, usefull iterator: we would like to create a filtered enumeration with regards to a given predicate. To do so, we first define the predicate interface (this interface defines a functor, funtion-like object)

public interface IPredicate<T>
{
    bool Invoke(T item);
}

And then, we can define the Select enumerator which returns the item of the predicate is true:

static public IEnumerable<T> Select<T>(IEnumerable<T> collection, IPredicate<T> pred)
{
    foreach(T item in collection)
    {
        if (pred.Invoke(item))
            yield return item;
    }
}

Let's apply this iterator to an example. Consider a list of string containing some names and a predicate that checks if a string starts with a particular string:

public class StartsWithPredicate : IPredicate<String>
{
    private string start;
    public StartsWithPredicate(string start)
    {
        this.start=start;
    }
    public bool Invoke(string item)
    {
        if (item==null)
            return false;
        return item.StartsWith(start);
    }
}

...
List<String> names = new List<String>();
names.Add("Marc");
names.Add("Jonathan");
names.Add("Julia");

Iterating and displaying the names that start with "J" is done using the Select method:

foreach(string name in Select(names, new StartWithPredicate("J")))
{ Console.WriteLine(name);}

-- output
Jonathan
Julia

This snippet is alreay nice but it is still quite verbose since we have to define a class before using it as a filter. It would be nice to use another new feature, namely anonymous methods, to define filters:

foreach(string name in Select(names, delegate(string s){ return s.StartsWith("J");}))
{ Console.WriteLine(name);}

In order to acheive this, we need to do 3 things: 1) declare a delegate that matches the signature of IPredicate.Invoke method, 2) create a IPredicate instance that wraps up a call to such delegate, 3) overload Select to take a delegate as argument:

// 1
public delegate bool PredicateDelegate(T item);

// 2
public class PredicateDelegateInvoker<T> : IPredicate<T>
{
   private PredicateDelegate<T> del;
   public PredicateDelegateInvoker(PredicateDelegate<T> del)
   {
      this.del = del;
   }
   public bool Invoke(T item)
   {
      return del(item);
   }
}

// 3
public IEnumerable<T> Select<T>(IEnumerable<T> collection, PredicateDelegate<T> pred)
{
   return Select(collection, new PredicateDelegateInvoker<T>(pred));
}

Now, we can use anonymous methods as shown above to filter any enumeration. In the following, I will define a framework to define a variety of enumerator, like in the good old days of STL.

Enumerator framework

1 Functors

First, we need to define some functor interfaces. There are two main families. Transformers take T instances as arguments and return a R instance. A transformer can accept one or two arguments (Binary). This interface represents the conversion T -> R:

public interface ITransformer<T,R>T
{
    R Invoke(T item);
}
public interface IBinaryTransformer<T,R>
{
    R Invoke(T left, T right);
}

Predicates are a specialized kind of transformer which returns bool:

public interface IPredicate<T> : ITransformer<T,bool>
{}

public interface IBinaryPredicate<T> : IBinaryTransformer<T,bool>
{}

There are a number of pre-built predicate that we can implement: And, Or, Not, etc... I will show how the And predicate, which applies the boolean and operator to the result of two IPredicate is implemented:

public class AndPredicate<T> : IPredicate<T>
{
    private IPredicate<T> leftPred;
    private IPredicate<T> rightPred;
    public AndPredicate(IPredicate<T> leftPred, IPredicate<T> rightPred)
    {
        this.leftPred = leftPred;
        this.rightPred = rightPred;
    }
    public bool Invoke(T value)
    {
        return leftPred.Invoke(value) && rightPred.Invoke(value);
    }
}

2 Delegates and delegate wrappers

As in the introductory example, we define 4 delegates and their functor wrapper for each functor interface:

public delegate R TransformerDelegate<T,R>(T item);
public delegate R BinaryTransformerDelegate<T,R>(T left, T right);
public delegate bool PredicateDelegate<T>(T item);
public delegate bool BinaryPredicateDelegate<T>(T left, T right);

+ wrappers

The wrappers are proxies to the delegate invokation.

3 Algorithms

Now that we are equipped with functors, we can start having fun and defining algorithms/enumerators.

3.1 Select

The Select enumerator (filtered enumeration) was already defined in the example, so we can skip it.

3.2 Transformation

The Transform enumerator applies a ITransformer to each item and returns the result:

static public IEnumerable<R> Transform<T,R>(
    IEnumerable<T> collection,
    ITransformer<T,R> transformer)
{
    foreach (T item in collection)
    {
        yield return transformer.Invoke(item);
    }
}

We also take care of writing the overload that handles anonymous methods. For example, we can use this method to convert all the strings in the names collection to upper case:

foreach(string upperCaseName in Transform<string,string>(names,delegate(string s){return s.ToUpper();}))
{Console.WriteLine(name);}

-- output
MARC
JONATHAN
JULIA

Note that in this case,  we need to specify the T,R parameters because the compiler cannot resolve them.

3.3 Others...

The list of possible enumeration is quite long, so I'll stop here for today.

Download the bits

You can download the bits from this example at www.dotnetwiki.org (look for Iterate project in the download section).

 

posted on Wednesday, August 11, 2004 4:24:00 AM UTC  #    Comments [4]
 Monday, August 09, 2004

Updated the "sick" Reflector.Graph release.

  • Compiled against .Net 1.0 and .Net 1.1 (1.0 version does not have the TreeMap)
  • Various bugs fixed

Download at www.dotnetwiki.org

posted on Monday, August 09, 2004 8:45:00 PM UTC  #    Comments [0]
 Saturday, August 07, 2004

There's one new cool feature of the VS2005 that has not received much attention, CodeSnippets. With CodeSnippets, you can write code template in minutes that are directly integrated into the intellisense of VS. That's great.... the sad point is that they are totally undocumented :(

CodeSnippets

Here's a small description of CodeSnippets in VS Express and here's a better tutorial but it is in french.

CodeSnippets for MbUnit

MbUnit has now CodeSnippets to create fixture, test methods, etc... all kinds of snippets that you write again and again. To set up the snippets, you need VS2005 and to download the MbUnit Code Snippets from www.dotnetwiki.org (they will be integrated in the next release).

Unzip the file in a directory and go to the menu Tools -> Code Snippets Manager... In the dialog, push Add and choose the directory where you have unzipped the snippets. The dialog window should look as follows. Clicking on each snippet will give you a short description, the shortcut to execute it, etc...

TestFixture snippet

In you need to create a new fixture, the TestFixture snippet is now here to help. Create a new blank C# file and write te. Intellisense window should pop out and now you will see new items: test, testfixture, etc...

 Go to the textfixture item and double "tab" it. The editor will execute the template and expand the item into an empty TestFixture class definition as follows:

 

You can also access the MbUnit expansion fixture by looking in the context menu, Intellisense -> Expand Item... -> MbUnitExpansion

posted on Sunday, August 08, 2004 3:52:00 AM UTC  #    Comments [5]
 Friday, August 06, 2004

The new TestFu.Gestures framework contains a set of classes to simulate user interaction, called "gestures". (Currently only the mouse is implemented) 

Why gestures ?

Lately, I've tackling the Windows.Forms problem. At first, I decided to use Reflection to get the On*** methods and use them to raise the events. This method worked for simple events such as Click but was showing some serious problem when you wanted to hit events like MouseEnter and MouseLeave. Obviously the Reflection solution was not good.

Let's think again about Form testing: we are mainly testing events that are triggered by user interaction (mouse or keyboard) so in order to test this, we should "mock" the user. The Form sees the user as a sequence of mouse or keyboard gestures, therefore, we need tools to generate artificial click, mouse moves, etc...

Gesture definition

A gesture can be any user input: mouse click, mouse move, key pressed, etc. A gesture can also be a combination of other gesture. For example, drag and drop is the sequence of mouse down, move, mouse up.

Generating mouse events

At first, I tried to simulate the mouse using the .Net class Cursor, but it was also showing limitation... so it seemed like this was a work for native methods and Interop. 

A quick googling over the subject showed that two methods from user32.dll where exactly designed for that: mouse_event and keybd_event. (I'll drop aside keybd_event for the moment). I found the correct C# signature and some example in the excellent www.pinkove.net site.

This method is harnessed in the state helper class VirtualInput which has several helper methods to simulate user interactions:

// simulate a left click
VirtualInput.MouseClick();
// move the mouse
VirtualInput.MouseMove(10,10);
// push right button down
VirtualInput.MouseDown(MouseButtons.Right);

Gestures interfaces

Now, that we have a method to generate mouse events, we can start to define the TestFu.Gesture framework. A gesture is defined by a simple interface:

public interface IGesture
{   
    Form Form{get;}
    void Start();
}

That's pretty minimalistic. The Start method executes the gesture and the Form represents the tested System.Windows.Form instance (we need it to convert coordinates between client and screen).

It is important to note that gestures should not be executed in the main thread, otherwize you will not simulate "correctly" the user interaction. Therefore, the signature of the Start method is intended to be easily "Theard startable".

A mouse gesture is defined by the IMouseGesture that specializes IGesture:

public interface IMouseGesture : IGesture
{
    MouseButtons Buttons {get;}
}

The Buttons property value gives the combination of mouse buttons involved in the gesture.

A simple gesture: the mouse click

To illustrate these interfaces, we show the mouse click gesture is implemented. This gesture inherits from an abstract base class MouseGestureBase, which implements IMouseGesture:

public class ClickMouseGesture : MouseGestureBase
{
   ... // constructors

   public override void Start()
   {
      VirtualInput.MouseClick(this.Buttons);
   }
}

In fact, this example shows well that gestures implement the Metod Invocation Object pattern (if I recall well).

A gesture factory

In order  to simplify things, TestFu.Gestures come with a factory for gestures object, GestureFactory. This factory contains a bunch of helper classes to save you time and keystrokes. In the following example, we use the factory to create a "click" gesture and execute it in a separate thread:

Form form =...; // target form
GestureFactory factory = new GestureFactory(form);

IGesture clik = factory.MouseClick();
GestureFactory.Start(click);

Gesture library

This section gives the list of available gestures with example. For the example, we suppose that we have a form that contains two controls (left and right) and a factory:

Form form = ...;
Control left = Form.LeftControl;
Control right = Form.RightControl;
GestureFactory factory = new GestureFactory(form);
  • Mouse click
    // click
    IGesture g = factory.MouseClick();
    // click control
    g = factory.MouseClick(left);
    // click location
    g = factory.MouseClick(new Point(10,20));
    
  • Mouse move
    // move to location
    g = factory.MouseMove(new Point(...,...));
    // move to the center of a control
    g = factory.MouseMove(left); 
    
  • Drag and drop between different locations
    // drag and drop between two controls
    g = DragAndDrop(left,right);
    
  • Sleep
    // sleep 1 sec
    g = factory.Sleep(1000);
  • Sequence of gestures
    // click left and then right
    g = factory.Sequence(
        factory.MouseClick(left),
        factory.MouseClick(right)
        );
  • Repeat a gesture
    // click left 3 times
    g = factory.Repeat(
        factory.MouseClick(left),
        3);
    
posted on Friday, August 06, 2004 10:43:00 PM UTC  #    Comments [11]
 Tuesday, August 03, 2004

This blog presents the filtering tools that QuickGraph contains. Filters enables you to create a filtered view of a vertex collection, edge collection, a vertex list graph or other more advanced graphs.

The basics:

All the filters relay on two interfaces: IVertexPredicate and IEdgePredicate. Both those interface have a Test method that takes a IVertex (resp. IEdge) as argument and returns true if the instance should be kept, or false if it should be filtered out. Special collection, in the System.Collections.Filtered namespace, can be used to create a filtered enumeration of vertices and edges.

Examples

Let's take the file dependency example, as introducted in Fun with Graphs (2): Drawing graphs with QuickGraph and NGraphviz

This graph is part of the QuickGraphTest demo project:

BidirectionalGraph graph = GraphProvider.FileDependency();

Filtering Vertices

The BidirectionalGraph class supports methods Select** that take a predicate as argument. We can use it to filter the vertices and display the source vertex only (a source has no in-edge):

Console.WriteLine("Source vertices:");
foreach(NamedVertex v in graph.SelectVertices(Preds.SourceVertex(graph)))
{
    Console.WriteLine("\t{0}",v.Name);
}

[Output]
Source vertices:
        zow.h
        boz.h
        dax.h

Preds is an static helper class. Preds.SourceVertex returns a SourceVertexPreicate instance implemented as follows:

using System;
namespace QuickGraph.Predicates
{
    using QuickGraph.Concepts;
    using QuickGraph.Concepts.Predicates;
    using QuickGraph.Concepts.Traversals;

    public class SourceVertexPredicate : IVertexPredicate
    {
        private IBidirectionalGraph graph;
        public SourceVertexPredicate(IBidirectionalGraph graph)
        {
            if (graph==null)
                throw new ArgumentNullException("graph");
            this.graph = graph;
        }

        bool IVertexPredicate.Test(IVertex v)
        {
            return this.graph.InEdgesEmpty(v);
        }
    }
}

In the case your graph does not implement Select methods, you can directly use filtered enumerable collection such as the FilteredVertexEnumerable. Here we will show the sinks of the graph:

Console.WriteLine("Sink vertices:");
FilteredVertexEnumerable filteredVertices =
    new FilteredVertexEnumerable(
        graph.Vertices,
        Preds.SinkVertex(graph)
    );
foreach (NamedVertex v in filteredVertices)
{
    Console.WriteLine("\t{0}",v.Name);
}

[Output]
Sink vertices:
        killerapp

Filtering edges

Edges can be filtered similarly to vertices using IEdgePredicate instances. The EdgePredicate class can be used to combine a IEdgePredicate and 2 IVertexPredicate for the source and the target of the edge.

Filtering entire graph

One can also creating filtered views of entire graphs. Let's consider another graph for this example: the finite state machine of a calculator:

 

In this case, we would like to filter out the S4 state and all the edges attached to this sate. One possible solution is to create a dictionary of vertices colors (VertexColorDictionary) where all the vertices are white, except S4 which is set to black.

// create and fill the dictionary
VertexColorDictionary vertexColors = new VertexColorDictionary();
IVertexPredicate pred = new NameEqualPredicate("S4");
foreach (IVertex v in graph.Vertices)
{
    if (pred.Test(v))
        vertexColors[v] = GraphColor.Black;
    else
        vertexColors[v] = GraphColor.White;
}

Then we can create the filters to ignore black vertices:

// create filters for the main graph
// no back vertex
IVertexPredicate vp = new NoBlackVertexPredicate(vertexColors);

// all edge that do not start or end on a blackvertex
IEdgePredicate ep = new EdgePredicate(
    Preds.KeepAllEdges(),
    vp
   );

At last, we use FilteredVertexAndEdgeListGraph to create a filtered IVertexListGraph

IVertexAndEdgeListGraph filteredGraph = new FilteredVertexAndEdgeListGraph(graph,ep,vp);

The image belows shows the result of the filtering. The S4 state and all its adjacent edges are gone.

posted on Tuesday, August 03, 2004 11:37:00 PM UTC  #    Comments [0]

The release 2.20 of MbUnit (bundled with TestFu and QuickGraph) has been released. See latest release page on this blog for the download links.This release was compiled against .Net v1.1. Note that MbUnit is now developped using Visual C# 2005 Express and compile using MSBuild (thanks to the expert help of Jamie Cansdale).

New features:

Breaking changes:

  •  The factories for the TypeFixture must tag the factory property with FactoryAttribute attribute

Bugs fixed:

  • Console appplication fixed,
  • Nant task fixed,
  • Assertion messages fixed,
  • NUnit fixture support fixed,
  • SqlAdministrator bugs fixed,
  • SqlGenerator fixed,
  • Random data generation of DataSet fixed 

 

posted on Tuesday, August 03, 2004 10:28:00 PM UTC  #    Comments [3]

In a previous post, I introduced DataGraph, a graph of the tables and relations available in TestFu. In this post, I present DataJoinGraph, the graph of a table join in a query:

  • Vertx: the DataTable and alias. Since a table can be referenced by multiple alias, the alias is used as the unique identifier of the vertex. Ex: User, "U"
  • Edge: the DataRelation and the type of join (Inner, Outer, etc...)

For the simple join situation (when two tables are simply linked), the DataJoinGraph uses the DataGraph of the database to resolve which DataRelation to use. (In the future, one could think about finding the minimum weight path and creating the join). For the moment, the DataJoinGraph can be used to create an ordering of joins, compatible with T-SQL. Let see this with some example

Creating the graph

DataJoinGraph lives in TestFu.Graph and takes a DataGraph as argument:

DataSet ds = ...;
DataJointGraph joinGraph = new DataJoinGraph(DataGraph.CreateGraph(ds));

Populating the graph

At first, you add the tables involved in the join with their alias (Note that aliases must be unique):

DataTableJoinVertex users = joinGraph.AddVertex(ds.Tables["Users"],"U");
DataTableJoinVertex orders = joinGraph.AddVertex(ds.Tables["Orders"],"O");

Afterwards, you add the different joins between the tables:

joinGraph.AddEdge(users,orders);

Since there is only one DataRelation linking users and orders, the DataJoinGraph can find the DataRelation to use. Moreover, by default we have use a Inner join but this can be modified by providing the proper parameter:

joinGraph.AddEdge(users,orders,JoinType.Outer);

This procedure is continued for the joins of the query.

Create an ordering

The DataTableJoinSortAlgorithm can be used to order the joins to create a SQL query:

DataTableJoinSortAlgorithm algo = new DataTableJoinSortAlgorithm(joinGraph);
algo.Compute();

The StartVertex property returns the first DataTableJoinVertex of the join, and the Joins property returns an ordered collection of DataRelationJoinEdge. For instance, the following method can be used to display the joins in SQL:

protected void ShowJoins()
{
    DataTableJoinVertex v = this.algo.StartVertex;
    Console.WriteLine("{0} AS {1}",v.Table.TableName, v.Alias);

    foreach (DataRelationJoinEdge edge in algo.Joins)
    {
        DataTableJoinVertex next = null;
        if (edge.Source==v)
            next = (DataTableJoinVertex)edge.Target;
        else
            next = (DataTableJoinVertex)edge.Source;
        Console.WriteLine("{0} JOIN {1} AS {2} ON ",
            edge.JoinType.ToString().ToUpper(),
            next.Table.TableName,
            next.Alias
            );

        bool needAnd=false;
        for (int i = 0; i < edge.Relation.ParentColumns.Length; ++i)
        {
            if (needAnd)
                Console.Write(" AND");
            else
                needAnd=true;
            Console.Write(" {0}.{1} = {2}.{3}",
                edge.Source.Alias,
                edge.Relation.ParentColumns[i].ColumnName,
                edge.Target.Alias,
                edge.Relation.ChildColumns[i].ColumnName
                );
        }
        Console.WriteLine();
        v = next;
    }
}

Some examples

Here are a few examples of use and their corresponding output using the ShowJoins method.

  • [C#]
    this.graph.AddVertex(this.dataSource.Users, "U");
    [Output]
    Users AS U
  • [C#]
    DataTableJoinVertex users = this.graph.AddVertex(this.dataSource.Users, "U");
    DataTableJoinVertex orders = this.graph.AddVertex(this.dataSource.Orders, "O");
    DataRelationJoinEdge uo = this.graph.AddEdge(users, orders, JoinType.Inner);
    [Output]
    Users AS U
    INNER JOIN Orders AS O ON 
     U.UserID = O.UserID
  • [C#]
    DataTableJoinVertex users = this.graph.AddVertex(this.dataSource.Users, "U");
    DataTableJoinVertex orders = this.graph.AddVertex(this.dataSource.Orders, "O");
    DataTableJoinVertex products = this.graph.AddVertex(this.dataSource.Products, "P");
    DataTableJoinVertex orderProducts = this.graph.AddVertex(this.dataSource.OrderProducts, "OP");
    DataRelationJoinEdge pop = this.graph.AddEdge(products, orderProducts, JoinType.Inner);
    DataRelationJoinEdge uo = this.graph.AddEdge(users, orders, JoinType.Inner);
    DataRelationJoinEdge oop = this.graph.AddEdge(orders, orderProducts, JoinType.Inner);
    
    [Output]
    Orders AS O
    INNER JOIN OrderProducts AS OP ON 
     O.OrderID = OP.OrderID
    INNER JOIN Products AS P ON 
     P.ProductID = OP.ProductID
    INNER JOIN Users AS U ON 
     U.UserID = O.UserID
    
posted on Tuesday, August 03, 2004 9:45:00 PM UTC  #    Comments [0]
 Friday, July 30, 2004

As MSBuild is getting more and more attention from the community, it was time for MbUnit to propose a MSBuild Task to execute the tests. This is now done (in the CVS) and the task will be available in the next release.

MSBuild Task Creation Process

I have used the MSDN articles on MSBuild as a good source of information for building the MbUnit task (see part 1 and part 2) from Christophe NasarreChristophe Nasarre. More specifically, the part 2 of the articles gives a detailled how-to on the custom task creation. I won't repeat the article here.

First impression: MSBuild way of defining custom properties is rather limited. I would have though that they could have used Xml serialization so that any serializable object could be used in the task definition. That's sad...

Ok, we start by creating a new project, added Microsoft.Build.Framework.dll and Microsoft.Build.Utilities.dll references and we add the MbUnit class.

using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using MbUnit....; // MbUnit usings

namespace MbUnit.MSBuild.Tasks
{
    public class MbUnit : Task
    {
        public override bool Execute()
        {
            ...
        }
    }
}

As you can see, the MbUnit class derives from Task, which implements ITask. The Execute method is invoked by MSBuild. Next step is to add some parameters to the task in order to setup the test execution. There are a bunch of them, I will focus on the test assembly paths:

public class MbUnit : Task
{
    private string[] assemblies;
    
    [Required]
    public string[] Assemblies
    {
        get { return this.assemblies; }
        set { this.assemblies = value; }
    }

Note the Required attribute which is used to mark required properties. We can now implement the main loop: the Execute method. The execute method outline is rather simple:

  • create an empty test report,
  • for each test assembly file path,
    • load the assembly in a separate AppDomain,
    • run tests,
    • merge results in the report
  • output the report to the desired formats
public override bool Execute()
{
    this.result = new ReportResult();
    try
    {
        foreach (string testFilePath in this.Assemblies)
        {
            string path = GetFilePath(testFilePath);
            if (path==null)
                return false;
            using (TestDomain domain = new TestDomain(path))
            {
                domain.ShadowCopyFiles = false;
                domain.Load();
                domain.TestTree.RunPipes();
                result.Merge(domain.TestTree.Report.Result);
            }
        }
        this.GenerateReports();
    }
    catch (Exception ex)
    {
        this.Log.LogError("Unexpected failure during MbUnit execution");
        return false;
    }
    return true;
}

It is time to prepare the project to debugging the task. As advised in the article, set the output path of the project to the .Net 2.0 folder and use MSBuild.exe as starting program. Put in the command line arguments the name of the XML file containing the MbUnit project.

Sample Project

This is a sample MSBuild project that executes MbUnit tests:


<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask AssemblyName="MbUnit.MSBuild.Tasks" TaskName="MbUnit.MSBuild.Tasks.MbUnit"/>

    <ItemGroup>
        <TestAssemblies Include="..\MbUnit.Demo\bin\Debug\MbUnit.Demo.exe" />
    </ItemGroup>

    <Target Name="Tests"> 
        <MbUnit
            Assemblies ="@(TestAssemblies)"
            HaltOnFailure="false"
            ReportTypes="Xml;Text;Html;Dox"
        /> 
    </Target>
</
Project>

The output of this task is as follows:

Microsoft (R) Build Engine Version 2.0.40607.16
[Microsoft .NET Framework, Version 2.0.40607.16]
Copyright (C) Microsoft Corporation 2004. All rights reserved.
Target "Tests" in project "ProjectSample.xml"
   Task "MbUnit"
      Loading C:\Documents and Settings\dehalleux\My Documents\Projects\mbunit\src\MbUnit.Demo\bin\Debug\MbUnit.Demo.exe
      Found  3 tests
      Running fixtures.
      Tests finished: 3 tests, 1 success, 2 failures, 0 ignored
      Unloading AppDomain
      All Tests finished: 3 tests, 1 success, 2 failures, 0 ignored in 1,56469663043767 seconds
      Generated Xml report at MbUnit.15_26_26.15_26_26.xml
      Generated Text report at MbUnit.15_26_26.15_26_26.txt
      Generated Html report at MbUnit.15_26_26.15_26_26.html
      Generated Dox report at MbUnit.15_26_26.15_26_26.dox.txt
I'll have a couple beers to this tonight :)
posted on Saturday, July 31, 2004 2:57:00 AM UTC  #    Comments [6]
 Thursday, July 29, 2004

I have sent the manuscript of my PhD to the jury today. The thesis speaks about stability and control of quasilinear hyperbolic partial differential equations (for example, stabilization of open channels). I won't speak about it in details here but I can give you the title:

Boundary Stabilization Techniques of Quasi-Linear Hyperbolic Initial-Boundary Value Problem.

Of course, the relation to software testing is not obvious... because there is none.

posted on Friday, July 30, 2004 3:19:00 AM UTC  #    Comments [2]
 Wednesday, July 28, 2004

The next version of MbUnit (2.20) will have a new custom attribute that will let you assert on the values of PerformanceCounters: PerfCounterAttribute. (Idea suggested by ISerializable). This means that you can make an assertion an every perfomance counter on your machine!

Here's a sample fixture that shows how the attribute can be used:

using System;
using MbUnit.Core.Framework;
using MbUnit.Framework;
namespace MbUnit.Demo
{
  [TestFixture]
  public class PerfCounterDemo
  {
    [Test]
    [PerfCounter(".NET CLR Memory", "% Time in GC", 10)]
    public void AllocateALotOfObjects()
    {
      ...
    }

    [Test]
    [PerfCounter(".NET CLR Loading", "% Time Loading", 10)]
    [PerfCounter(".NET CLR Security", "% Time in RT checks", 10000)]
    [PerfCounter(".NET CLR Security", "% Time Sig. Authenticating", 10)]
    [PerfCounter(".NET CLR Memory", "# Bytes in all Heaps", 5000000, Relative =true)]
    [PerfCounter(".NET CLR Jit", "% Time in Jit", 10)]
    public void MonitorMultipleCounters()
    {
      ...
    }
  }
}

Note that if you are too lazy to remember the names of the counters, I have written a CodeSmith template that creates a class filled with static helper methods for retreiving the counters. For example, the following class lets you write things like PerfCounterInfo.NetClrExceptions.NbofExcepsThrown.NextValue() using intellisense and without typing errors :)

using System;
using System.Diagnostics;
namespace MbUnit.Core.Framework
{
 public class PerfCounterInfo
 {  
  public sealed class NetClrExceptions
  {
   const string categoryName = @".NET CLR Exceptions";

   public sealed class NbofExcepsThrown
   {
    const string counterName = @"# of Exceps Thrown";

    public static float NextValue()
    {
     return NextValue(Process.GetCurrentProcess().ProcessName);
    }    
   }
   ...
posted on Thursday, July 29, 2004 5:29:00 AM UTC  #    Comments [8]

The next version of TestFu will feature a DataSet graph object (DataGraph class) , i.e. a bidirectional directed graph G(V,E) where

  • V is the set of vertices, one vertex per DataTable in the DataSet, (DataTableVertex class)
  • E is the set of edges, one edge per DataRelation in the DataSet (DataRelationEdge class). The source vertex of the edge is the ParentTable, while the target is the ChildTable.

Why do we need a graph ?

Once you have the graph structure of the database, you use all the algorithms contained in the QuickGraph.Algorithms project: shortest path, topological sort, etc... In fact, you can even use it to draw the graph using the NGraphviz. There are of course other very interresting applications of this structure. For example, you can use the graph to create a table creation order such that will not violate the constraints, or you estimate the complixity of a join, etc...

Let's see some examples..

Creating a graph and basic usage

DataGraph lives in the TestFu.Data.Graph namespace and is built from a DataSet instance:

using Test.Data.Graph;
...
DataSet ds = ...;
DataGraph graph = DataGraph.Create(ds);

Now that we have a graph, we can iterate over it's vertices and edges:

// iterating the vertices (DataTableVertex)
foreach(DataTableVertex v in graph.Vertices)
{
    DataTable table = v.Table;
    ...
}

// iterating the edges
foreach(DataRelationEdge e in graph.Edges)
{
   DataRelation relation = e.Relation;
   ...
}

Let's see what other things we could do with graph.

Drawing the table structure:

This is an obvious usage of the graph and can be done quite easily using the QuickGraph.Algorithms.Graphviz.GraphvizAlgorithm class:

GraphvizAlgorithm gv = new GraphvizAlgorithm(this.graph);
gv.FormatVertex+=new FormatVertexEventHandler(gv_FormatVertex);
gv.FormatEdge+=new FormatEdgeEventHandler(gv_FormatEdge);
System.Diagnostics.Process.Start(gv.Write(dataSource.DataSetName));

...

void gv_FormatVertex(object sender, FormatVertexEventArgs e)
{
    DataTableVertex v = (DataTableVertex)e.Vertex;
    e.VertexFormatter.Shape = NGraphviz.Helpers.GraphvizVertexShape.Box;
    e.VertexFormatter.Label = v.Table.TableName;
}
void gv_FormatEdge(object sender, FormatEdgeEventArgs e)
{
    DataRelationEdge edge = (DataRelationEdge)e.Edge;
    e.EdgeFormatter.Label.Value = edge.Relation.RelationName;
}

The result on a sample DataSet is displayed below:

DataTable ordering

Another interresting application is to create an ordering of the DataTable such that if you fill the tables using this ordering, you will not break any constraint. This solves the old problem "which table should I populate first?". For example, in the example above, the ordering result would be:

  1. Users,
  2. Orders,
  3. Categories,
  4. Products,
  5. OrderProducts

Since this feature has a major interrest in TestFu, it is built-in in the DataGraph class:

DataTable[] tables = graph.GetSortedTables();
In the background, graph uses the QuickGraph.Algorithms.SourceFirstTopologicalSortAlgorithm algorithm class which creates a topological ordering of the vertices of a graph by choosing the vertices with least in degree (very simple algo, home made):

// sort tables
SourceFirstTopologicalSortAlgorithm topo = new SourceFirstTopologicalSortAlgorithm(graph);
topo.Compute();

// output results
DataTable[] result = new DataTable[topo.SortedVertices.Count];
int i = 0;
foreach (DataTableVertex v in topo.SortedVertices)
{
    result[i++] = v.Table;
}
return result;

The SourceFirstTopologicalSortAlgorithm takes a IVertexAndEdgeListGraph instance which graph implements. As you can see, having a graph representation of your DataSet, compatible with QuickGraph opens a realm interresting applications of existing graph theory algorithms.

Next step: "Smart" Random Data generation

Once the table ordering is computed, you can safely generate "smart" random data and feed your DataSet...

posted on Wednesday, July 28, 2004 11:29:00 PM UTC  #    Comments [6]

While writing the test for the NUnit fixture loader, I started to have some twisted tests. So twisted, they are worth mentionned in the blog. For instance, the steps I take to test NUnit load are:

  1. Load a NUnit fixture from the Assembly resources (as source code),
  2. Compile it and output an assembly using CodeDom.Compiler namespace,
  3. Load the newly created assembly using MbUnit, look for the tests and execute,
  4. Verify that the tests have been found, are executed and behaved as expected.
  5. Execute all those steps in a fixture

Twisted...

 

using System;
using System.IO;
using System.Configuration;
using System.Reflection;
using MbUnit.Core.Remoting;
using MbUnit.Core.Framework;
using MbUnit.Framework;
using MbUnit.Framework.Utils;
using System.CodeDom.Compiler;
using MbUnit.Core.Reports;
using MbUnit.Core.Reports.Serialization;
namespace MbUnit.Tests.Core.FrameworkBridges
{
  [TestFixture]
  [CurrentFixture]
  public class NUnitBridgeTest
  {
    private SnippetCompiler compiler;
    private ReportCounter counter;
    private ReportResult result;

    [SetUp]
    public void SetUp()
    {
      this.compiler = new SnippetCompiler();
      string nunitFolder = ConfigurationSettings.AppSettings["NUnitFolder"];
      string nunitFrameworkDll = Path.Combine(nunitFolder,@"NUnit.Framework.dll");
      this.compiler.Parameters.ReferencedAssemblies.Add(nunitFrameworkDll);
      this.compiler.LoadFromResource(
         "