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(
         "MbUnit.Tests.Core.FrameworkBridges.NUnitFixture.cs",
         Assembly.GetExecutingAssembly()
        );
      string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
      this.compiler.Parameters.OutputAssembly =
          Path.Combine(path, "NUnitBridgeTest.dll");
    }

    [Test]
    public void TestCaseCount()
    {
      LoadAndRunFixture();
      Assert.AreEqual(4, counter.RunCount);
    }

    [Test]
    public void SuccessCount()
    {
      LoadAndRunFixture();
      Assert.AreEqual(2, counter.SuccessCount);
    }

    ...

    private void LoadAndRunFixture()
    {
      this.compiler.Parameters.GenerateInMemory = false;
      this.compiler.Compile();
      this.compiler.ShowErrors(Console.Out);
      Assert.IsFalse(this.compiler.Results.Errors.HasErrors);

      // load assembly using MbUnit
      using (TestDomain domain = new TestDomain(this.compiler.Parameters.OutputAssembly))
      {
        domain.ShadowCopyFiles = false;
        domain.Load();

        // running tests
        domain.TestTree.RunPipes();
        
        result = domain.TestTree.Report.Result;
        counter = domain.TestTree.GetTestCount();
      }
    }
  }
}

And the loaded fixture is as follows:

using System;
using System.IO;
using NUnit.Framework;
namespace MbUnit.Tests.Core.FrameworkBridges
{
  [TestFixture]
  public class NUnitFixture
  {
    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
      Console.Out.Write("TestFixtureSetUp");
    }
    [SetUp]
    public void SetUp()
    {
      Console.Out.Write("SetUp");
    }
    [Test]
    public void Success()
    {
      Console.Out.Write("Success");
    }
    [Test]
    public void Failure()
    {
      Console.Out.Write("Failure");
      Assert.Fail();
    }
    [Test]
    [ExpectedException(typeof(ArgumentNullException))]
    public void ExpectedException()
    {
      Console.Out.Write("ExpectedException");
      throw new ArgumentNullException("boom");
    }
    [Test]
    [Ignore("Because I want")]
    public void Ignore()
    {
      Console.Out.Write("Ignore");
      throw new Exception("Ignored test");
    }
    [TearDown]
    public void TearDown()
    {
      Console.Out.Write("TearDown");
    }
    [TestFixtureTearDown]
    public void FixtureTearDown()
    {
      Console.Out.Write("FixtureTearDown");
    }
  }
}
posted on Wednesday, July 28, 2004 8:17:00 AM UTC  #    Comments [2]
 Sunday, July 25, 2004
Download available at www.dotnetwiki.org download page.
posted on Sunday, July 25, 2004 11:24:00 PM UTC  #    Comments [4]
 Saturday, July 24, 2004

Reflector.Graph has been recompiled for Reflector 4.0.15.0 along with some bug fixes (unit test generation is working again).

Download it in the www.dotnetwiki.org download section.

posted on Sunday, July 25, 2004 3:33:00 AM UTC  #    Comments [8]

This release brings more userfriendlyness to the GUI and generally it returns more information on what MbUnit is doing. See latest release page on this blog for the download links.

New features:

  • New progress bar displaying number of tests, successs, failures, ignore and test duration,
  • Status bar displaying more information,
  • Console application does pop report by default,
  • Added TestDox report type,
  • MbUnit gui can load and save projects (assemblies + treeview state is serialized)

Screenshot of the "new" gui

posted on Sunday, July 25, 2004 12:39:00 AM UTC  #    Comments [0]
 Friday, July 23, 2004

MbUnit supports a new report type, similar to TestDox. This reports creates a simple text file, whith fixture and test case names more human readable.

For example, a Test fixture like

[TestFixture]
public class FooTest
{
    [Test]
    public void IsASingletonTest() {}
    [Test]
    public void AReallyLongNameIsAGoodThing() {}
}

MbUnit generates

-- MbUnit.Demo
MbUnit
MbUnit.Demo
    Foo
        - is a singleton
        - a really long name is a good thing

Available in 2.18.1

posted on Saturday, July 24, 2004 3:04:00 AM UTC  #    Comments [0]

MbUnit now supports a simple way of running a single fixture (the one you are working on) without the need of a GUI or NUnitAddIn. The method is simple: tag your fixture class with the CurrentFixtureAttribute and launch it with the auto-runner:

Consider this little example:

[TestFixture]
public class MyFixture
{
   ...
}
  1. Tag MyFixture with CurrentFixtureAttribute:
  2. Convert the test assembly to a console application and add the following code to your main function:
    using System;
    namespace MbUnit.Tests
    {
        using MbUnit.Core;
        using MbUnit.Core.Filters;
        public class AutoRunTest
        {
            public static void Main(string[] args)
            {
                using(AutoRunner auto = new AutoRunner()) 
                {
                    auto.Domain.Filter = FixtureFilters.Current;
                    auto.Run();
                    auto.ReportToHtml();
                }
            }
        }
    }
    
  3. Launch the console. The fixture will be executed and a HTML report of the tests will pop-out automatically.
(available in 2.18.1)
posted on Friday, July 23, 2004 9:42:00 PM UTC  #    Comments [0]

This is a question that I received a few times: Peli is my nickname, which was given to me by my parents. Their memory on the reason why is somehow vague:

  • It could comes from the pelican (the bird) because of the movie "Jonathan Livingstone the Seagul", which became a pelican,
  • because Pelican have a big mouth,
  • because my mom did not like "Jonathan"  with the french pronounciation

Cheers,

Peli...

posted on Friday, July 23, 2004 10:31:00 AM UTC  #    Comments [2]
 Thursday, July 22, 2004

New features:

 See latest release page on this blog for the download links

posted on Thursday, July 22, 2004 11:02:00 PM UTC  #    Comments [5]
 Wednesday, July 21, 2004

The API Design Guidelines encourage developers to check all their arguments and thereby avoid throwing a NullReferenceException.  If an argument is null and the contract of the method forbids null arguments an ArgumentNullException should be thrown. Brad Adams 

So you agree with Brad (I do) and you always check that arguments are not null before using them. This means a little bit more of code but it is worth it. But this means also a lot more of test code because, ideally, you should test that all your methods check all their arguments. This means writing hundreds of boring, repetitive test cases.... and you don't want to do that.

At least I don't so I added a new feature to MbUnit that does it for me.

Test for ArgumentNullException, first iteration:

 Let's see how it works with an example:

public class ArgumentNullDummyClass
{
    public object ClassicMethod(Object nullable, Object notNullable, int valueType)
    {
        if (notNullable == null)
            throw new ArgumentNullException("notNullable");
        return String.Format("{0}{1}{2}",nullable,notNullable,valueType);
    }
}

As one can see, the nullable parameter can be null, while the notNullable parameter is tested. Now, let's create a fixture that tests this method. We will be using the TestSuiteFixture because we will build a TestSuite:

[TestSuiteFixture]
public class MethodTestSuiteDemo
{
    public delegate object MultiArgumentDelegate(Object o,Object b, int i);
    
    [TestSuite]
    public ITestSuite AutomaticClassicMethodSuite()
    {
        ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();

        MethodTester suite = new MethodTester(
            "ClassicMethod",
            new MultiArgumentDelegate(dummy.ClassicMethod),
            "hello",
            "world",
            1
            );
            suite.AddAllThrowArgumentNull();
        return suite.Suite;
    }
}

The MethodTester class takes the following argument: a name, a delegate  and valid parameters of the delegate. By valid I mean parameters that should not make the delegate invokation fail. The AddAllThrowArgumentNull looks for nullable parameters and create a TestCase that will invoke the delegate with the corresponding parameter nulled. In the example, this means that ClassicMethod will be called with:

  • null, "world", 1
  • "hello", null, 1

Test for ArgumentNullException, second iteration:

There are things I don't like in the example above:

  • you need to create a delegate (tedious),
  • you need to create 1 method tester per method (tedious),

Ok, so let's build a ClassTester class that does that for us... The test code now looks as follows:

[TestSuiteFixture]
public class ClassTesterDemo
{
    [TestSuite]
    public ITestSuite AutomaticClassSuite()
    {
        ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();
        ClassTester suite = new ClassTester("DummyClassTest",dummy);
        suite.Add("ClassicMethod","hello","world",1);
        return suite.Suite;
    }
}

That's much better: delegate is gone and we could add more methods to be tested in a single call.

Test for ArgumentNullException, third iteration:

There is still one problem with this technique: there is no way to tell that an argument is authorized to be nulled! In the example, the nullable parameter can be null and the TestCase will always fail because it does not throw ArgumentNullException.

The solution of this problem is done in two steps: first, you, the developper, tag the parameters that can be nulled with a NullableAttribute attribute (could be any of your attributes). In the example, we add a SmartMethod method and the MyNullableAttribute:

[AttributeUsage(AttributeTargets.Parameter,AllowMultiple=false,Inherited=true)]
public class MyNullableAttribute : Attribute
{}

public class ArgumentNullDummyClass
{
    public object ClassicMethod(Object nullable, Object notNullable, int valueType)
    {...}
    public object SmartMethod([MyNullable]Object nullable, Object notNullable, int valueType)
    {...}
}

Next, you must tell MbUnit which attribute is used to tag nullable parameters. This is done with the NullableAttributeAttribute at the assembly level:

[assembly: NullableAttribute(typeof(MbUnit.Demo.MyNullableAttribute))]

Ok, now we just need to update our test case to load the SmartMethod:

[TestSuite]
public ITestSuite AutomaticClassSuite()
{
    ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();
    ClassTester suite = new ClassTester("DummyClassTest",dummy);

    suite.Add("ClassicMethod","hello","world",1);
    suite.Add("SmartMethod","hello","world",1);

    return suite.Suite;
}

The result in MbUnit GUI is as follows: the parameters of ClassicMethod were all tested, nullable included which we want to avoid. The parameters of SmartMethod were all tested excluded nullable because it was tagged. :)

Test for ArgumentNullException, fourth iteration:

 

The more I think about this problem, the more I think FxCop should do that for us...

posted on Thursday, July 22, 2004 12:37:00 AM UTC  #    Comments [0]

The API Design Guidelines encourage developers to check all their arguments and thereby avoid throwing a NullReferenceException.  If an argument is null and the contract of the method forbids null arguments an ArgumentNullException should be thrown. Brad Adams 

So you agree with Brad (I do) and you always check that arguments are not null before using them. This means a little bit more of code but it is worth it. But this means also a lot more of test code because, ideally, you should test that all your methods check all their arguments. This means writing hundreds of boring, repetitive test cases.... and you don't want to do that.

At least I don't so I added a new feature to MbUnit that does it for me.

Test for ArgumentNullException, first iteration:

 Let's see how it works with an example:

public class ArgumentNullDummyClass
{
    public object ClassicMethod(Object nullable, Object notNullable, int valueType)
    {
        if (notNullable == null)
            throw new ArgumentNullException("notNullable");
        return String.Format("{0}{1}{2}",nullable,notNullable,valueType);
    }
}

As one can see, the nullable parameter can be null, while the notNullable parameter is tested. Now, let's create a fixture that tests this method. We will be using the TestSuiteFixture because we will build a TestSuite:

[TestSuiteFixture]
public class MethodTestSuiteDemo
{
    public delegate object MultiArgumentDelegate(Object o,Object b, int i);
    
    [TestSuite]
    public ITestSuite AutomaticClassicMethodSuite()
    {
        ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();

        MethodTester suite = new MethodTester(
            "ClassicMethod",
            new MultiArgumentDelegate(dummy.ClassicMethod),
            "hello",
            "world",
            1
            );
            suite.AddAllThrowArgumentNull();
        return suite.Suite;
    }
}

The MethodTester class takes the following argument: a name, a delegate  and valid parameters of the delegate. By valid I mean parameters that should not make the delegate invokation fail. The AddAllThrowArgumentNull looks for nullable parameters and create a TestCase that will invoke the delegate with the corresponding parameter nulled. In the example, this means that ClassicMethod will be called with:

  • null, "world", 1
  • "hello", null, 1

Test for ArgumentNullException, second iteration:

There are things I don't like in the example above:

  • you need to create a delegate (tedious),
  • you need to create 1 method tester per method (tedious),

Ok, so let's build a ClassTester class that does that for us... The test code now looks as follows:

[TestSuiteFixture]
public class ClassTesterDemo
{
    [TestSuite]
    public ITestSuite AutomaticClassSuite()
    {
        ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();
        ClassTester suite = new ClassTester("DummyClassTest",dummy);
        suite.Add("ClassicMethod","hello","world",1);
        return suite.Suite;
    }
}

That's much better: delegate is gone and we could add more methods to be tested in a single call.

Test for ArgumentNullException, third iteration:

There is still one problem with this technique: there is no way to tell that an argument is authorized to be nulled! In the example, the nullable parameter can be null and the TestCase will always fail because it does not throw ArgumentNullException.

The solution of this problem is done in two steps: first, you, the developper, tag the parameters that can be nulled with a NullableAttribute attribute (could be any of your attributes). In the example, we add a SmartMethod method and the MyNullableAttribute:

[AttributeUsage(AttributeTargets.Parameter,AllowMultiple=false,Inherited=true)]
public class MyNullableAttribute : Attribute
{}

public class ArgumentNullDummyClass
{
    public object ClassicMethod(Object nullable, Object notNullable, int valueType)
    {...}
    public object SmartMethod([MyNullable]Object nullable, Object notNullable, int valueType)
    {...}
}

Next, you must tell MbUnit which attribute is used to tag nullable parameters. This is done with the NullableAttributeAttribute at the assembly level:

[assembly: NullableAttribute(typeof(MbUnit.Demo.MyNullableAttribute))]

Ok, now we just need to update our test case to load the SmartMethod:

[TestSuite]
public ITestSuite AutomaticClassSuite()
{
    ArgumentNullDummyClass dummy = new ArgumentNullDummyClass();
    ClassTester suite = new ClassTester("DummyClassTest",dummy);

    suite.Add("ClassicMethod","hello","world",1);
    suite.Add("SmartMethod","hello","world",1);

    return suite.Suite;
}

The result in MbUnit GUI is as follows: the parameters of ClassicMethod were all tested, nullable included which we want to avoid. The parameters of SmartMethod were all tested excluded nullable because it was tagged. :)

Test for ArgumentNullException, fourth iteration:

 

The more I think about this problem, the more I think FxCop should do that for us...

posted on Thursday, July 22, 2004 12:37:00 AM UTC  #    Comments [4]
 Tuesday, July 20, 2004

MbUnit now supports the new attributes for Roy Osherove (ISerializable) to solve the database Rollback problem:

  • SqlRestoreInfoAttribute contains the information necessary to perform database restore (connection string, etc...),
  • RollBackAttribute uses EnterpriseServices to roll back the transactions done in the test case, (Note that this attribute does not rely on SqlRestoreInfo and can live on its own)
  • RestoreDatabaseFirstAttribute, restores the database before starting the test (using DbAdministrator from TestFu).

I will assume that you have read the article from Roy so I can skip explanation and show an example. Consider the following test fixture:

[TestFixture]
[SqlRestoreInfo("connectionstring","databasename",@"c:\backups\nw.mbk")]
public class NorthWindTest
{
    [Test, RollBack]
    public void TestWithRollBack()
    {...}

    [Test, RestoreDatabaseFirst]
    public void TestWithRestoreFirst()
    {...}
}

This example, which runs in MbUnit,  is similar to what Roy has proposed: SqlRestoreInfo gives information that can be used to restore the db. TestWithRollBack is rolled back using Enterprise services, the database is restored before TestWithRestoreFirst is executed.

What about data abstraction ?

We would like to create a fixture and apply it to different Db provider (Oracle, MySql,etc..). Is this possible ? This is (will**) possible in a minimum of work, it is just a matter of changing SqlRestoreInfo to OracleRestoreInfo:

[TestFixture]
public abstract class DbNorthwindTest
{
    [Test, RollBack]
    public void TestWithRollBack()
    {...}

    [Test, RestoreDatabaseFirst]
    public void TestWithRestoreFirst()
    {...}
}

[SqlRestoreInfo("connectionstring","databasename",@"c:\backups\nw.mbk")]
public class SqlNorthwindTest : DbNorthwindTest
{}

[OracleRestoreInfo("connectionstring","databasename",@"c:\backups\nwporacle.mbk")]
public class OracleNorthwindTest : DbNorthwindTest
{}

This example is quite neat and self-explenatory: SqlNorthwindTest will apply the fixture against a MsSql server using System.Data.SqlClient classes, while OracleNorthwindTest will test against Oracle.

**Currently, only SqlRestoreInfoAttribute is implemented.

posted on Wednesday, July 21, 2004 3:51:00 AM UTC  #    Comments [22]
 Monday, July 19, 2004

TestSuite are suites of test dynamically created. This is a feature that was requested long ago and it finally poped up on my todo list. A TestSuite provides a way of creating dynamically TestCases with tightly-controlled naming. For example, in data-driven testing, you might want to create test cases based on some external data source.

How-to in MbUnit

To use suites, tag your calss with the TestSuiteFixtureAttribute attribute. Each method who creates suite must be tagged with TestSuiteAttribute and return a TestSuite, there can be multiple methods returning suites.

using System;
using MbUnit.Core.Framework;
using MbUnit.Framework;
namespace MyNamespace
{
    [TestSuiteFixture]
    public class MyClass
    {
        public delegate void TestDelegate(Object context);
        [TestSuite] 
        public TestSuite GetSuite()
        {
            TestSuite suite = new TestSuite("Suite1");
            suite.Add( "Test1", new TestDelegate( this.Test ), "hello" );
            suite.Add( "Test2", new TestDelegate( this.AnotherTest), "another test" );
            return suite;
        }
        public void Test( object testContext )
        {
            Console.WriteLine("Test");
            Assert.AreEqual("hello", testContext);
        }
        public void AnotherTest( object testContext )
        {
            Console.WriteLine("AnotherTest");
            Assert.AreEqual("another test", testContext);
        }
    }
}

The resulting naming of the fixture will be as follows:

MyNamespace.MyClass.Suite1.Test1
MyNamespace.MyClass.Suite1.Test2

Not that the namespace name and the class name are used to create the test case name, the name of the method creating the suite is not used. The resulting output of the tests in MbUnit will look as follows:

posted on Tuesday, July 20, 2004 4:43:00 AM UTC  #    Comments [6]

MbUnit (2.16.1) has now the ability to load and run NUnit (and csUnit) assemblies without recompilation.

How it works

Jamie Cansdale (NUnitAddin) sent me some classes he was using in his Addin to execute NUnit assemblies. Thank you Jamie :). When a type is explored, it looks into the referenced assemblies for NUnit.Framework.dll or csUnit.Framework.dll. If found, it thens extracts the TestFixtureAttribute type and tests if the type is tagged with it. A couple more details and there you have NUnit tests run by MbUnit...

Sample:

The following sample fixture is a standard NUnit fixture:

using System;
using NUnit.Framework;
namespace MbUnit.Tests.Core.FrameworkBridges
{
    [TestFixture]
    public class NUnitFrameworkTest
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            Console.WriteLine("TestFixtureSetUp");
        }
        [SetUp]
        public void SetUp()
        {
            Console.WriteLine("SetUp");
        }
        [Test]
        public void Test()
        {
            Console.WriteLine("Test");
        }
        [Test]
        public void AnotherTest()
        {
            Console.WriteLine("Another test");
        }
        [Test]
        [ExpectedException(typeof(AssertionException))]
        public void ExpectedException()
        {
            Assert.Fail("Should be intercepted");
        }
        [Test]
        [Ignore("Testing ignore")]
        public void Ignored()
        {
            Assert.Fail("Must be ignored");
        }
        [TearDown]
        public void TearDown()
        {
            Console.WriteLine("TearDown");
        }
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            Console.WriteLine("TestFixtureTearDown");
        }
    }
}

The  fixture is loaded and executed by MbUnit and the reports shows:

posted on Tuesday, July 20, 2004 2:10:00 AM UTC  #    Comments [12]

The MbUnit.Core.AutoRun class is a new lightweight class that explores and executes the tests contained in the entry assembly. This class can be used to create executable test assemblies that are self-contained.

public class AutoRunTest
{
    public static void Main(string[] args)
    {
        using(MbUnit.Core.AutoRunner auto = new MbUnit.Core.AutoRunner())
        {
            auto.Run();
            auto.ReportToHtml();
        }
    }
}

The AutoRunner class also supports filtering and will be available in 2.16.1.

posted on Monday, July 19, 2004 9:38:00 PM UTC  #    Comments [4]

At last, MbUnit loads the assemblies in separate AppDomain and do not lock them...

This release brings the "much awaited" shadow copying feature to MbUnit which means that you can do real TDD development with the GUI. This part of the code has been strongly inspired from the NUnit implementation. Copyright notice have been kept in the source code.

Release Details

  • Separate AppDomain for each test assembly,
  • Handling configuration files as in NUnit (test assembly name + ".config"),
  • Test assembly monitoring and reloading when changes detected,
  • Filtering in the console application,

Many other bugs have been also fixed...

Download MbUnit 2.16beta at www.dotnetwiki.org

 

posted on Monday, July 19, 2004 11:10:00 AM UTC  #    Comments [10]
 Sunday, July 18, 2004

More and more visualization of the coverage: ThreadTree and Xml:

The ThreadTree is a control available in the Data Visualization Components suite from Microsoft Research, it displays a tree where the nodes are sorted by a ranking. In this case, the tree is the Namespace / Type hierarchy and the ranking is the coverage. Not very useful, but very pretty.

 

The Xml views shows the actual output of NCover.

posted on Sunday, July 18, 2004 11:48:00 AM UTC  #    Comments [3]

Just added a Tree and the Microsoft TreeMap to visualize the coverage results:

posted on Sunday, July 18, 2004 10:55:00 AM UTC  #    Comments [4]
 Saturday, July 17, 2004

I have freshened up the NCover project to build a simple Gui around it. Not much work, just some Category attributes to put there and there...

posted on Saturday, July 17, 2004 2:00:00 PM UTC  #    Comments [3]
 Friday, July 16, 2004

This blog presents an implementation of an Ant Colony Optimization (ACO) framework using Visual C# 2005 Express.

What is ACO ?

ACO is the evolution of the Ant Algorithms, algorithms that were based on observation on ants. It is a metaheuristic algorithm that is used to solve complex problems (NP-hard) such as the Travelling Salesman Problem(in this problem, a salesman has to travel across each city in a minimum distance). There is a lot of litterate on ACO and TSP on the web...

Where does it come from ?

My implementation is based on the book Ant Colony Optimization from Marco Dorigo. I must say that the authors have takened care of giving clear and well-detailled pseudo-code to make an implementation easy.

The first results

Here are some outputs of the TSP computation of burma14 using my framework. The red line represents the best-so-far solution, the other lines are colored with respect to their pheromone intensity.

  • Iteration 1:
  • Iteration 7:
  • Iteration 28:
  • Iteration 33:
  • Iteration 54:

Download

The download called MetaHeuristics is available on the download page of www.dotnetwiki.org .

posted on Saturday, July 17, 2004 5:37:00 AM UTC  #    Comments [8]

This tutorial shows the basic usage of NCover from GotDotNet. The tutorial starts by creating a toy solution, how to set-up NCover execution, analysis and improvements of the results.

A toy solution

  1. Create a new solution,
  2. Add a C# assembly project named UnderCover,
  3. Add a class JamesBond defined as follows:
    using System;
    namespace UnderCover
    {
        public class JamesBond
        {
            public void Covered()
            {
                Console.WriteLine("Covered");
            }
            public void UnCovered()
            {
                Console.WriteLine("UnCovered");
            }
        }
    }
  4. Add a C# console application project name UnderCover.Console.exe
  5. Edit the Main entry method as follows:
    using System;
    namespace UnderCover.Cons
    {
        class Class1
        {
            [STAThread]
            static void Main(string[] args)
            {
                JamesBond james = new JamesBond();
                james.Covered();
            }
        }
    }
  6. Compile in debug mode
    Note: NCover needs the symbol files (.mdb) in order to work, so you need to work with the debug version.

Our objective is now to compute the coverage of UnderCover.dll when UnderCover.Console.exe is executed. It is straightforward to see that JamesBond.Covered will be fully covered while JamesBond.UnCovered will be not covered.

Setting a NCover batch file

In this step, we create a simple batch file in the bin/debug directory to execute NCover.Console.exe with the command line. The NCover command line takes the command line to execute + the assembly to cover as parameters:

"C:\Program Files\NCover\NCover.Console.exe" /c "UnderCover.Cons.exe" "UnderCover.dll" /v

The output of NCover is as follows

"C:\Program Files\NCover\NCover.Console.exe" /c "UnderCover.Cons.exe" "Under
Cover.dll" /v
NCover.Console v1.3.3 - Code Coverage Analysis for .NET - http://ncover.org

Command: UnderCover.Cons.exe
Command Args: UnderCover.dll
Working Directory:
Assemblies:
Coverage File:
Coverage Log:
******************* Program Output *******************
Covered
***************** End Program Output *****************
Copied 'C:\Program Files\NCover\Coverage.xsl' to '...\Coverage.xsl'

If everything executed correctly, a Coverage.xml and Coverage.xsl has appeared in the directory.

First look at the results

Open Coverage.xml in your browser and you will get something like this:

The coverage has worked, we have the expected results.

Better XSLT template

Now, this works fine for a simple assembly but the files becomes huge if you have a normal project so we need a better XSLT template. MbUnit has it's own NCover Coverage.xsl template (that you can get here) that supportes expand/collapse and computes the percents of coverages. Let us copy the new coverage.xsl to the directory:

Now this looks much better :)

Results in Reflector

As I showed in a previous post, the Reflector Code Coverage Addin can help you visualize the coverage in a more intuitive way. The steps to follow are:

  1. Add Reflector.TreeMap.dll as a Addin of Reflector,
  2. Load UnderCover.dll,
  3. Right-click on UnderCover assembly and choose Coverage TreeMap,
  4. Right-click on the TreeMap and load the Coverage.xml file
  5. Enjoy the results:

Downloads:

The solution of this tutorial is available in the download section of www.dotnetwiki.org .

posted on Friday, July 16, 2004 12:54:00 PM UTC  #    Comments [13]

Just loaded the MbUnit solution in Visual C# Express 2005 and.... it worked without a single problem! Looks like we will have MbUnit for .NET 2.0 in the next release :)


posted on Friday, July 16, 2004 8:04:00 AM UTC  #    Comments [3]
 Thursday, July 15, 2004

The MbUnit Console Runner Application has undergone a major "plastic surgery" to prepare the next release of MbUnit. The new features are :

  • Report output to Xml, Html or Text, or a combination of those. The output directory of the reports can also be specified in the command line,
  • Filtering of the fixture by
    • Namespace,
    • Type full name,
    • Category,
    • Author name,
    • Importanc
  • Each of the filter can be multiple, i.e. you can filter multiple