# Thursday, September 30, 2004

MbUnit has been released as part of the new TestDriven.NET build. Please check Jamies blog for the links to the downloads. MbUnit is now compiled using a complex build setup that is described on Jamie's blog.

Change log

  • Assembly loading had problems in the previous version. All should be fixed now,
  • RollbackAttribute is back in a separate assembly (MbUnit.Framework.1.1.dll) compiled against .NET 1.1
  • Added Assembly Dependencies and Fixture dependencies
  • Better TD.NET integration

 

posted on Thursday, September 30, 2004 9:29:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [2]
I have stumbled on this web site: http://iv.slis.indiana.edu/index.html It has amazing examples of data visualization!
posted on Thursday, September 30, 2004 11:46:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [1]
# Wednesday, September 29, 2004

FlexWiki is an evolved WikiWikiWeb implementation for .NET. It has an extensible internal language, called WikiTalk, that can be used to extend the framework with new behaviors. I'm currently exploring this framework with some nifty ideas... here's a first snapshot: a behavior that renders the graph of the pages (all the nodes are clickable)

 

posted on Wednesday, September 29, 2004 11:30:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [7]

Following the idea of Fixture dependency, I have added Assembly dependencies as well: execute tests from child assembly only if parents were successful.

Similarly, we use the AssemblyDependsOnAttribute to specify the parent assemblies:

[assembly: MbUnit.Core.Framework.AssemblyDependsOn("AnotherAssembly")]
posted on Wednesday, September 29, 2004 11:24:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [1]

MbUnit now supports setting dependencies between fixtures, similarly to NAnt/MSBuild task dependencies.

How-to

The logic is simple. You can tag a fixture with the DependsOnAttribute to specify a "parent" fixture that should be run before the current fixture. If the parent fixture fails, the current fixture is not run:

[TestFixture]
public class Parent
{...}

[TestFixture]
[DependsOn(typeof(Parent))]
public class Child
{...}

The Child fixture is executed if the Parent fixture executed successfully.

Why do we need dependencies between fixtures ?

Image that you are testing a database. At first, you create a fixture that tests that the connection is correct:

[TestFixture]
public class ConnectionTest
{ ... }

If one of the tests of ConnectionTest fails, then it is likely that all the tests that rely on a database connection will fail and, therefore, should not be executed. Using the DependsOnAttribute, you can specify the dependency of such fixture to the ConnectionFixture.

[TestFixture]
[DependsOn(typeof(Connection))]
public class DALTest
{...}

An example

The following example defines 4 fixture. Child depends on Parent and SickParent, GrandChild depends on Child. Since SickParent has a failed test, Child and GrandChild should not be executed...

[TestFixture]
[CurrentFixture]
public class Parent
{
    [Test]
    public void Success()
    {}
}

[TestFixture]
[CurrentFixture]
public class SickParent
{
    [Test]
    public void Failure()
    {
        throw new Exception("boom");
    }
}

[TestFixture]
[CurrentFixture]
[DependsOn(typeof(Parent))]
[DependsOn(typeof(SickParent))]
public class Child
{
    [Test]
    public void Success()
    {
    }
}

[TestFixture]
[CurrentFixture]
[DependsOn(typeof(Child))]
public class GrandChild
{
    [Test]
    public void Success()
    {}
}

The report result is shown below and one can see that Child and GrandChild fixture have failed without being executed.

posted on Wednesday, September 29, 2004 7:00:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [10]
After 4 years working in CESAME, I finally graduated as Doctor in Applied Mathematics :)
posted on Wednesday, September 29, 2004 10:42:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [23]
# Friday, September 24, 2004

MbUnit has now the ability of re-executing the failed tests cases and ignoring the successful tests.  A test case filter loads the previous XML result from a file and filters all the fixture that have not failed.

QuickStart example

This is the main function of MbUnit.Demo. We use the AutoRunner to make an assembly that is self-executable and we set the special filter (FailureRunPipeFilter). This filter will try to load the previous report. If it finds it, it will use the information to ignore successfull tests.

public static void Main(string[] args)

{

using (AutoRunner auto = new AutoRunner())

{

// creating the report name

string reportName = Path.GetFullPath(String.Format("{0}.xml", auto.GetReportName()));

 

FailureRunPipeFilter filter = new FailureRunPipeFilter(reportName);

auto.Domain.RunPipeFilter = filter;

 

auto.Run();

auto.ReportToHtml();

auto.ReportToXml(false);

}

}

Results:

I have executed twice MbUnit.Demo (don't be afraid about the number of failures, they are intentional, it's a demo!) The first report shows the first run result and second shows the second run report... Abracadadra, only failed tests remain

posted on Friday, September 24, 2004 2:31:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [1]
# Thursday, September 23, 2004

This is a preview of a new language for Reflector that outputs to Refly (Refly is wraps up and simplifies the use of CodeDom).

What does the language do ?

The language creates Refly code. If the Refly code is executed it will generate the original code. This is particularly usefull to rapidely design CodeDom template: write the expected output, Reflectorize-it and get the Refly code. In the figure below, we see the code "cycle of life" with a decompiler and how it is modified if we add the "Refly" language.

A preview example

There is still a lot of work to do on the language but it can already generate the outline of classes. Let's see that on a simple class:

public class Original

{

private string name;

public Original()

{}

public string Name

{

get { return this.name;}

set { this.name = value;}

}

public void Run(string someParamter)

{

Console.WriteLine("{0}: someParameter");

}

public event EventHandler Click;

protected virtual void OnClick(EventArgs e)

{

if (this.Click != null)

this.Click(this, e);

}

}

After compiling and  loading in Reflector, the Refly language is outputting:

NamespaceDeclaration _dragAndDropUnitTesting = new NamespaceDeclaration("Original");

 

ClassDeclaration _original = _dragAndDropUnitTesting.AddClass("Original");

 

// Fields

FieldDeclaration name = _original.AddField(typeof(System.String), "name");

FieldDeclaration Click = _original.AddField(typeof(System.EventHandler), "Click");

 

// Events

EventDeclaration _click = _original.AddEvent(typeof(System.EventHandler), "Click");

 

// Constructor and Methods

ConstructorDeclaration ctor0 = _original.AddConstructor();

ctor0.Attributes |= System.CodeDom.MemberAttributes.Assembly;

ctor0.Attributes |= System.CodeDom.MemberAttributes.Family;

MethodDeclaration _run = _original.AddMethod("Run");

_run.Attributes |= System.CodeDom.MemberAttributes.Assembly;

_run.Attributes |= System.CodeDom.MemberAttributes.Family;

ParameterDeclaration _runsomeParamter = _run.Signature.Parameters.Add(typeof(System.String), "someParamter");

MethodDeclaration _onClick = _original.AddMethod("OnClick");

_onClick.Attributes |= System.CodeDom.MemberAttributes.Family;

ParameterDeclaration _onClicke = _onClick.Signature.Parameters.Add(typeof(System.EventArgs), "e");

 

// Properties

PropertyDeclaration _name = _original.AddProperty(typeof(System.String), "Name");

 

That's pretty ugly but not as much if you had to write CodeDom for that. We can compile and generate the code using the following instruction:

CodeGenerator gen = new CodeGenerator();
gen.GenerateCode(".", _dragAndDropUnitTesting);

Finally, the output of the execution is as follows:

using System;

/// <summary />

/// <remarks />

public class Original

{

/// <summary />

/// <remarks />

private string _name;

/// <summary />

/// <remarks />

private System.EventHandler _click;

/// <summary />

/// <remarks />

Original()

{

}

/// <summary />

/// <remarks />

public virtual string Name

{

}

/// <summary />

/// <remarks />

public event System.EventHandler Click;

/// <summary />

/// <remarks />

void Run(string someParamter)

{

}

/// <summary />

/// <remarks />

void OnClick(System.EventArgs e)

{

}

}

Of course, the result is far from behing perfect. Visibility handling sucks, statements are not reflected, etc... But sounds very promising to me :)

posted on Thursday, September 23, 2004 12:30:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [11]
Just sent the manuscript of the my thesis to the printer... One last step (public presentation) and I'm free!
posted on Thursday, September 23, 2004 8:17:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [6]
# Wednesday, September 22, 2004

Reflector.Graph has been updated for Reflector 4.1.6.0.

Download available at www.dotnetwiki.org

posted on Wednesday, September 22, 2004 6:32:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [6]
# Tuesday, September 21, 2004

This is the first release candidate for MbUnit 2.21.1.0. This release also contains QuickGraph (+NGraphviz), Refly and TestFu.

Acknowledgment
I'd like to give a special thanks to Jamie Cansdale (TestDriven.NET) which has been the main architect of the new MbUnit compilation scripts,  installers and TestDriven.NET intergration.

Installing MbUnit 2.21.1.0 RC1

[Update: follow the instructions at http://www.testdriven.net/wiki/default.aspx/MyWiki.DownLoad]

Where is MbUnit installed ?

The MbUnit assemblies are located in Program Files/TestDriven.NET/MbUnit.

New features

 

posted on Tuesday, September 21, 2004 9:49:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [22]
# Sunday, September 19, 2004

Sorry, I can' resist putting little animation of the new design-time support in MbUnit. This sample shows how you can easily set up monitoring on a few PerformanceCounter inside a fixture component. (Demo solution at http://blog.dotnetwiki.org/downloads/DragAndDropUnitTesting.zip )

How-to

The procedure to monitor a PerformanceCounter is as follows:

  1. Add any PerformanceCounter to the component (drag and drop from the Toolbox),
  2. Make sure they are set up,
  3. For each PerformanceCounter, add a PerformanceCounterChecker and associate it a PerformanceCounter instance in the property pane
  4. Add the desired tests

For each of the test, the PerformanceCounterChecker will monitor the value of it's associated counter and it will assert if the value goes out of the specified bounds. In the report, a little summary of the counter values is shown (in the Console.Out view of the report).

posted on Sunday, September 19, 2004 8:58:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [6]

I've recently discovered Context in .Net while reading the Programming .Net Components book (Chapter 11). This is an amazing piece of technology that I definitely needed to try. A first try was to make a Caching context:

Caching context

Image that you have methods that perform long computation, such as querying a database etc..., and return a result. Usually, the result does not change much over time, so typically you would like to cache the results in order to improve the efficiency of the application. Now imagine that there exists a Caching context that would take care of caching method calls. For example, we would like to write something like this:

[Caching]
public class CachedClass : ContextBoundObject
{
    [Cached]
    public string ReturnBigObject()
    { 
        Console.WriteLine("miss");
        Thread.Sleep(1000);
        return DateTime.Now.ToString(); 
    }
}

In that sample, we would like the output of ReturnBigObject to be cached. For example, the sample method below shows the desired behavior. The first call to ReturnBigObject is a cache miss and then, the remaining calls are cached.

miss
c.ReturnBigObject(): 5/10/2004 19:31:31
c.ReturnBigObject(): 5/10/2004 19:31:31
c.ReturnBigObject(): 5/10/2004 19:31:31

Let's see the steps to take to create the caching context:

Building the context (1): CachingAttribute

The CachingAttribute has to inherit from ContextAttribute and override two methods. The main task of the attribute is to add a IContextProperty implementation to the context properties (GetPropertiesForNewContext method). 

[AttributeUsage(AttributeTargets.Class,AllowMultiple =false,Inherited =true)]
public class CachingAttribute : ContextAttribute
{
    public CachingAttribute():base("Chaching")
    {}
    public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
    {
        IContextProperty property =
            new CachingContextProperty(ctorMsg.ActivationType);
        ctorMsg.ContextProperties.Add(property);
    }
    public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
    {
        return false;
    }
}

Building the context (1.1): CachedAttribute

The CachedAttribute is used to tag method to be cached. It contains several parameters to set up the HttpRuntime.Cache object.

Building the context (2): CachingContextProperty

The task of this class is to install a server IMessageSink in the message flow that will cache the message calls. Therefore, this class implements IContextProperty, IContributeServerContextSink.

public class CachingContextProperty : 
    IContextProperty, IContributeServerContextSink
{
    private Type activationType;
    ...
    public IMessageSink GetServerContextSink(IMessageSink nextSink)
    {
        CachingSink cachingSink = new CachingSink(nextSink, activationType);
        return cachingSink;
    }
}

Building the context (3): CachingSink

This is where the real work occurs. This class filters the call to the method (IMethodMessage) and looks in a Cache (HttpRuntime.Cache) if it is stored, if stored it returns the value, otherwize it calls the next sink and store the value in the Cache. (This part of the code is a little bit more technical because a part of the IMethodReturnMessage has to be "copied").

The heart of this class is as follows:

public IMethodReturnMessage SyncProcessMessage(IMethodMessage msg)
{
    // creating unique hash value out of method, instance and paramteres
    string hash = Hash(msg);
    // looking in the cache
    IMethodReturnMessage returnMessage = HttpRuntime.Cache[hash] as IMethodReturnMessage;
    if (returnMessage != null) // cache hit
        return returnMessage;
    
    returnMessage = this.Parent.NextSink.SyncProcessMessage(msg) 
        as IMethodReturnMessage;

    // caching returned information
    CachedMethodReturnMessage cachedMessage= new CachedMethodReturnMessage(returnMessage);

    // storing in cache
    HttpRuntime.Cache.Add(hash, cachedMessage,
        this.cachedAttribute.Dependencies,
        this.cachedAttribute.AbsoluteExpiration,
        this.cachedAttribute.SlidingExpiration,
        this.cachedAttribute.Priority,
        null);
    IMethodReturnMessage r = HttpRuntime.Cache[hash] as IMethodReturnMessage;
    return returnMessage;
}

Downloads

The full source is available on www.dotnetwiki.org

 

posted on Sunday, September 19, 2004 4:50:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [12]

I've recently discovered Context in .Net while reading the Programming .Net Components book (Chapter 11). This is an amazing piece of technology that I definitely needed to try. A first try was to make a Caching context:

Caching context

Image that you have methods that perform long computation, such as querying a database etc..., and return a result. Usually, the result does not change much over time, so typically you would like to cache the results in order to improve the efficiency of the application. Now imagine that there exists a Caching context that would take care of caching method calls. For example, we would like to write something like this:

[Caching]
public class CachedClass : ContextBoundObject
{
    [Cached]
    public string ReturnBigObject()
    { 
        Console.WriteLine("miss");
        Thread.Sleep(1000);
        return DateTime.Now.ToString(); 
    }
}

In that sample, we would like the output of ReturnBigObject to be cached. For example, the sample method below shows the desired behavior. The first call to ReturnBigObject is a cache miss and then, the remaining calls are cached.

miss
c.ReturnBigObject(): 5/10/2004 19:31:31
c.ReturnBigObject(): 5/10/2004 19:31:31
c.ReturnBigObject(): 5/10/2004 19:31:31

Let's see the steps to take to create the caching context:

Building the context (1): CachingAttribute

The CachingAttribute has to inherit from ContextAttribute and override two methods. The main task of the attribute is to add a IContextProperty implementation to the context properties (GetPropertiesForNewContext method). 

[AttributeUsage(AttributeTargets.Class,AllowMultiple =false,Inherited =true)]
public class CachingAttribute : ContextAttribute
{
    public CachingAttribute():base("Chaching")
    {}
    public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
    {
        IContextProperty property =
            new CachingContextProperty(ctorMsg.ActivationType);
        ctorMsg.ContextProperties.Add(property);
    }
    public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
    {
        return false;
    }
}

Building the context (1.1): CachedAttribute

The CachedAttribute is used to tag method to be cached. It contains several parameters to set up the HttpRuntime.Cache object.

Building the context (2): CachingContextProperty

The task of this class is to install a server IMessageSink in the message flow that will cache the message calls. Therefore, this class implements IContextProperty, IContributeServerContextSink.

public class CachingContextProperty : 
    IContextProperty, IContributeServerContextSink
{
    private Type activationType;
    ...
    public IMessageSink GetServerContextSink(IMessageSink nextSink)
    {
        CachingSink cachingSink = new CachingSink(nextSink, activationType);
        return cachingSink;
    }
}

Building the context (3): CachingSink

This is where the real work occurs. This class filters the call to the method (IMethodMessage) and looks in a Cache (HttpRuntime.Cache) if it is stored, if stored it returns the value, otherwize it calls the next sink and store the value in the Cache. (This part of the code is a little bit more technical because a part of the IMethodReturnMessage has to be "copied").

The heart of this class is as follows:

public IMethodReturnMessage SyncProcessMessage(IMethodMessage msg)
{
    // creating unique hash value out of method, instance and paramteres
    string hash = Hash(msg);
    // looking in the cache
    IMethodReturnMessage returnMessage = HttpRuntime.Cache[hash] as IMethodReturnMessage;
    if (returnMessage != null) // cache hit
        return returnMessage;
    
    returnMessage = this.Parent.NextSink.SyncProcessMessage(msg) 
        as IMethodReturnMessage;

    // caching returned information
    CachedMethodReturnMessage cachedMessage= new CachedMethodReturnMessage(returnMessage);

    // storing in cache
    HttpRuntime.Cache.Add(hash, cachedMessage,
        this.cachedAttribute.Dependencies,
        this.cachedAttribute.AbsoluteExpiration,
        this.cachedAttribute.SlidingExpiration,
        this.cachedAttribute.Priority,
        null);
    IMethodReturnMessage r = HttpRuntime.Cache[hash] as IMethodReturnMessage;
    return returnMessage;
}

Downloads

The full source is available on www.dotnetwiki.org

 

posted on Sunday, September 19, 2004 4:50:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [12]
# Saturday, September 18, 2004

Following the example of drag and drop unit tests. I have added support for the classic ExpectedException behavior as well as the four Setup, TearDown, FixtureSetUp, FixtureTearDown methods (sorry another screen grad).

 

posted on Saturday, September 18, 2004 4:15:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [5]

Following the example of drag and drop unit tests. I have added support for the classic ExpectedException behavior as well as the four Setup, TearDown, FixtureSetUp, FixtureTearDown methods (sorry another screen grad).

 

posted on Saturday, September 18, 2004 4:15:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [5]
# Friday, September 17, 2004

Reflector.Graph release for Reflector 4.1.5.0 available at www.dotnetwiki.org

[Update] Changed Reflector.Graph back to an assembly

New addins:

 

 

posted on Friday, September 17, 2004 6:12:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [8]

Reflector.Graph release for Reflector 4.1.5.0 available at www.dotnetwiki.org

[Update] Changed Reflector.Graph back to an assembly

New addins:

 

 

posted on Friday, September 17, 2004 6:12:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [8]
# Thursday, September 16, 2004

Image that you could open the designer, drag and drop a few test case, and run them with minimal writing... now take a look at this:

(Download a demo solution at http://blog.dotnetwiki.org/downloads/DragAndDropUnitTesting.zip )

posted on Thursday, September 16, 2004 2:52:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [20]

Image that you could open the designer, drag and drop a few test case, and run them with minimal writing... now take a look at this:

(Download a demo solution at http://blog.dotnetwiki.org/downloads/DragAndDropUnitTesting.zip )

posted on Thursday, September 16, 2004 2:52:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [20]

Introduction

Have you ever wondered how you could animate armies of thousands of soldiers ? flocks of hunderds of fish ? etc... Well, you use what they call Autonomous Agents: agents that have a local behavior that creates interresting global behaviors. The first example of autonomous agents was brought in 1984 by Craig Reynolds which developped a small application to simulation flocks: the boids application was born.

Since then, Reynolds has published an excellent paper in 99 on the subject: Steering behavior for Autonomous Characteres. If you never had a look at this, check out his web site and look at the java demo, it is just splendid!

Previous try

During my Phd, I monitored the course of C/C++ for third year Engineer students. The autonomous agents theme was very appealing and students got very involved into that project. (If you are looking for something fun for teaching software engineering, this theme is great!). At that time, they received a mini drawing library that could render agents in real time in OpenGL and Glut. If you want to give it a try, you can download it from www.dotnetwiki.org (look for Autonomous.binaries.zip in the download section) Of course, I tested the project on myself and built an application that looked as follows:

 

On the picture, you can see 151 agent (green dots) that are moving toward the little black dot. They are avoiding themselves, avoiding obstacles (big gray circle). The little lines between agents show that there is a "flocking" interaction,i.e. they are avoiding themselves.

During that project, we could see a lot of interresting properties of such flocks. For example, the system has a self-organization property. If you let the simulation go long enough, agents will organize themselves in a perfect triangular tiling as show below:

We could also see waves where the agents stopped going in reverse direction from the direction of the flock (In PDE theory, those are called shocks). In fact, it is the same phenomenon that occurs in traffic jam when a wave a "zero" velocity is travelling along the highway. When you stand back in your car, just look at the way you will start run a few hundred meters and the stop, and again and again. This behavior is predicted by the hyperbolic PDE theory :) In the figure below, the agents are moving left toward the little black dot. You can visualize the waves going right. The gray lines denote flock which means that agents are stopping in order to avoid each other.

NSteer

The code C++ was written using Tempate Meta Programming. In NSteer, I'll try to build gradually a framework for C#

posted on Thursday, September 16, 2004 9:16:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [8]

Introduction

Have you ever wondered how you could animate armies of thousands of soldiers ? flocks of hunderds of fish ? etc... Well, you use what they call Autonomous Agents: agents that have a local behavior that creates interresting global behaviors. The first example of autonomous agents was brought in 1984 by Craig Reynolds which developped a small application to simulation flocks: the boids application was born.

Since then, Reynolds has published an excellent paper in 99 on the subject: Steering behavior for Autonomous Characteres. If you never had a look at this, check out his web site and look at the java demo, it is just splendid!

Previous try

During my Phd, I monitored the course of C/C++ for third year Engineer students. The autonomous agents theme was very appealing and students got very involved into that project. (If you are looking for something fun for teaching software engineering, this theme is great!). At that time, they received a mini drawing library that could render agents in real time in OpenGL and Glut. If you want to give it a try, you can download it from www.dotnetwiki.org (look for Autonomous.binaries.zip in the download section) Of course, I tested the project on myself and built an application that looked as follows:

 

On the picture, you can see 151 agent (green dots) that are moving toward the little black dot. They are avoiding themselves, avoiding obstacles (big gray circle). The little lines between agents show that there is a "flocking" interaction,i.e. they are avoiding themselves.

During that project, we could see a lot of interresting properties of such flocks. For example, the system has a self-organization property. If you let the simulation go long enough, agents will organize themselves in a perfect triangular tiling as show below:

We could also see waves where the agents stopped going in reverse direction from the direction of the flock (In PDE theory, those are called shocks). In fact, it is the same phenomenon that occurs in traffic jam when a wave a "zero" velocity is travelling along the highway. When you stand back in your car, just look at the way you will start run a few hundred meters and the stop, and again and again. This behavior is predicted by the hyperbolic PDE theory :) In the figure below, the agents are moving left toward the little black dot. You can visualize the waves going right. The gray lines denote flock which means that agents are stopping in order to avoid each other.

NSteer

The code C++ was written using Tempate Meta Programming. In NSteer, I'll try to build gradually a framework for C#

posted on Thursday, September 16, 2004 9:16:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [8]
# Friday, September 10, 2004

The full source of the BENUG presentation is available for download at http://blog.dotnetwiki.org/downloads/benug.package.zip

The file contains the two presentation I did (TFU.pdf and DPF.pdf in the Showtime folder), the CodeSmith templates and the sample project solution. The first presentation gave a quick introduction to unit testing tools + basic database testing. The second paper presented a new way of handling database testing through intelligent data generators (Database Populator Framework).

If you want to do the exercise of the DPF presentation, you should install TestDriven.Net....msi on your machine. Make sure you remove NUnitAddIn before doing that. This file is a special build of NUnitAddIn (now named TestDriven.Net) that ships with MbUnit.

posted on Friday, September 10, 2004 7:11:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [13]

The full source of the BENUG presentation is available for download at http://blog.dotnetwiki.org/downloads/benug.package.zip

The file contains the two presentation I did (TFU.pdf and DPF.pdf in the Showtime folder), the CodeSmith templates and the sample project solution. The first presentation gave a quick introduction to unit testing tools + basic database testing. The second paper presented a new way of handling database testing through intelligent data generators (Database Populator Framework).

If you want to do the exercise of the DPF presentation, you should install TestDriven.Net....msi on your machine. Make sure you remove NUnitAddIn before doing that. This file is a special build of NUnitAddIn (now named TestDriven.Net) that ships with MbUnit.

posted on Friday, September 10, 2004 7:11:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [13]
# Monday, September 06, 2004

This addin explores a Typed DataSet generated by the Visual Studio and creates the table structure. For the example, selecting the NorthwindDataSet, you will get this output:

 

posted on Monday, September 06, 2004 8:04:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [5]

This addin explores a Typed DataSet generated by the Visual Studio and creates the table structure. For the example, selecting the NorthwindDataSet, you will get this output:

 

posted on Monday, September 06, 2004 8:04:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [5]

Reflector.Graph now builds and diplays the list of available addins and their menu location. Look for the Tools -> List of Reflector.Graph Addins menu item.

posted on Monday, September 06, 2004 1:11:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [2]

The TestFu Database Populator Framework (DPF presented here) is a framework for generating data for database testing. Given a DataSet, the framework can build a "smart" data generator to you can later use in your databse testing. I will present this at BENUG on sep. 9.

Why this framework ?

When you try to apply unit testing to database, you choices are not much: use transaction - clean up you "mess" after each test or even worse backup and restore the database on each test. In fact, there is an intrisic problem with unit testing of database: you cannot ensure the atomicity of each test, i.e. you cannot leave a database in the state that it was prior to the test (you could by restoring the db  from file at each test, but this is costly).

For example, transaction through enterprise services (see Roy's Rollback attribute) works great... but if you are using IDENTITY columns, then the identity counter is not reseted by the transaction and thus, the test case are correlated.

Now, what if we wanted to build unit tests for database that would not require clean up. This would mean that new data should be generated at each execution, since the previous execution would not have been cleaned up. This is where DPF comes into the picture: the DPF engine will generate new data for each of your unit test execution at no cost.

Generating random data is not difficult

That's true, the System.Random class is easy to use. However, things gets (a bit) more complicated when you generate data for database because you have to ensure that integrity constraint are enforced. This is why you will need such framework.

DPF How-to

The DPF totally relies on DataSet and comes with a few CodeSmith templates to accelerate development. The following how-to could be applied to any of your database.

  1. If not done yet, create the strongly-typed DataSet of your database. You can do this by adding a new Typed DataSet to your project and drag and drop the tables in the designer. (Make sure VS has imported the constraint).
  2. Open the DatabasePopulator.cst template. This template willl create a "strongly typed" database populator for a given database,
     
    where
    • Database will let you choose a database available on your machine, select the target database here,
    • Namespace  is the namespace of the strongly typed generator class,
    • TableNamePrefix is the table prefix in your database (in case there is one). This prefix will be trimmed to create the class names
  3. Open the CrudPopulator.cst template and edit it in order to match the way your DAL access the database. This template will generate populator class that can apply CRUD operation to your database. You can also directly use that template and edit each "throw new NotImplementedException()" statement. (I strongly suggest you edit it the template for your needs).
  4. Open the DatabasePopulatorTest.cst tempate and generate a fixture. This template will generate a fixture that will test each CRUD operation of each table in the database. The data necessary to those tests will be automatically generated by the populator.

 

posted on Monday, September 06, 2004 11:38:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [8]

Jamie Cansdale has also started to build new Reflector.Graph addins. This new addin creates a simple UML-like class diagram around the selected type.

Some facts:

  • All the nodes of the graph are clickable wich makes it an easy way of navigation the type hierachy,
  • Base class is marked in blue, which a filled arrow
  • Methods and properties are marked with + (public), - (private), # (protected) and @ (internal)

Congrats Jamie!

posted on Monday, September 06, 2004 10:52:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [4]
# Saturday, September 04, 2004

Reflector version: 4.1.4.0
Reflector.Graph version: 4.1.4.0
Download: www.dotnetwiki.org

Before getting the new version, make sure you have a look at the release notes below!

New Addins

This is the first release of the statement graph. It is surely not perfect. If you find anomalies in your graph, please prepare a code example that shows the problem and send it to me :)

posted on Saturday, September 04, 2004 10:13:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [4]
# Thursday, September 02, 2004

TestFixtureSetUp and TestFixtureTearDown

MbUnit now supports TestFixtureSetUp and TestFixtuteTearDown attribute to mark methods to be executed at the beginning of a fixture test case execution and at the end.

[TestFixture]
public class Fixture
{
    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {...}

    ...

    [TestFixturteTearDown]
    public void TestFixtureTearDown()
    {...}
}
  • Both method are optional and are allowed once per class,
  • If TestFixtureSetUp invocation fails, no test case are executed and they are all marked as failures,
  • TestFixtureTearDown is always invoked,
  • If TestFixtureTearDown fails, all the test cases are marked as failure
  • TestFixtureSetUp and TestFixtureTearDown are executed on the same instance. This is not ensured for the other methods,
  • Output in those methods are recorded in the reports

AssemblyCleanUp, SetUp and TearDown

MbUnit also support test assembly setup and teardown. Those methods should be enclosed in a class that is feeded to the AssemblyCleanUpAttribute (Assembly attribute, thanks Omer), They must be public and static. The setup method must be tagged with SetUpAttribute, and the teardown method with TearDownAttribute:

[assembly: AssemblyCleanUp(typeof(AssemblyCleaner))]
...
public class AssemblyCleaner
{
    [SetUp]
    public static void SetUp()
    {
        Console.WriteLine("Setting up {0}", typeof(AssemblyCleanUp).Assembly.FullName);
    }
    [TearDown]
    public static void TearDown()
    {
        Console.WriteLine("Cleaning up {0}", typeof(AssemblyCleanUp).Assembly.FullName);
    }
}
  • Only one class with AssemblyCleanUp per assembly is authorized,
  • Both methods are optional,
  • If SetUp fails, no tests are run and they are all marked as failure,
  • TearDown is always executed.
  • If TearDown fails, all the tests are marked as failure
posted on Thursday, September 02, 2004 4:20:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [20]
# Wednesday, September 01, 2004

This new Reflector.Addin creates a Method Graph where the vertex are methods, and the edges represent an invokation of a method. By clicking on the vertices, you jump to the next method, while keeping record of your previous steps.

Let's see this on FileStream.WriteByte method as shown above. The figure above is generated by right-clicking on the FileStream method and selecting "Method Invokation Graph". If I choose to to click FlushRight, the graph changes to:

 

Click on the next vertex will grow the tree, more and more...
posted on Wednesday, September 01, 2004 6:17:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [1]

I have revamped my TestFixture generator to work with the StatementGraph (i.e. FlowGraph). The generator logics has not changed:

  1. Build the Statement Graph from the method,
  2. Extract the path necessary to cover the entire graph (cover all statements in the method),
  3. Create one method for each path
  4. In each method documentation, output the decompiled code where the "target" statements have been highlighted.

Disclaimer

  1. This generator is far from behing finished or optimal: the algorithm to produce the graph is not optimal, I have not implement the Newyork Street Sweeper algorithm yet,
  2. If your code is buggy, the generator will generate tests for ... buggy code.

Examples

Here's a sample of what gets output from the examples in the StatementGraph article. Targetted statements are marked with /* i */ where i is the index of the tested statement

/// <summary>Test fixture for the &lt;see cref="StatementSamples"/&gt; class</summary>

/// <remarks />

[TestFixture()]

public class StatementSamplesTest

{

/// <summary>Tests the Simple method</summary>

/// <remarks>

/// <para>Test coverage (estimated): 100,0%</para>

/// <para>Target path:</para>

/// <code>/* 0 */ Console.WriteLine("hello");

/// </code>

/// </remarks>

[Test()]

[Ignore("NotImplemented")]

public virtual void Simple0()

{}

/// <summary>Tests the Block method</summary>

/// <remarks>

/// <para>Test coverage (estimated): 100,0%</para>

/// <para>Target path:</para>

/// <code>/* 0 */ Console.WriteLine("hello");

/// /* 1 */ Console.WriteLine("world");

/// </code>

/// </remarks>

[Test()]

[Ignore("NotImplemented")]

public virtual void Block0()

{}

/// <summary>Tests the If method</summary>

/// <remarks>

/// <para>Test coverage (estimated): 83,3%</para>

/// <para>Target path:</para>

/// <code>/* 0 */ if (value &lt; 0)

/// {

/// /* 1 */ Console.WriteLine("true");

/// /* 2 */ return;

/// }

/// Console.WriteLine("false");

/// </code>

/// </remarks>

[Test()]

[Ignore("NotImplemented")]

public virtual void If0()

{}

/// <summary>Tests the If method</summary>

/// <remarks>

/// <para>Test coverage (estimated): 50,0%</para>

/// <para>Target path:</para>

/// <code>/* 0 */ if (value &lt; 0)

/// {

/// Console.WriteLine("true");

/// return;

/// }

/// /* 1 */ Console.WriteLine("false");

/// </code>

/// </remarks>

[Test()]

[Ignore("NotImplemented")]

public virtual void If1()

{}

/// <summary>Tests the While method</summary>

/// <remarks>

/// <para>Test coverage (estimated): 100,0%</para>

/// <para>Target path:</para>

/// <code>/* 0 */ int num1 = 0;

/// while ((num1 &lt; 10))

/// {

/// /* 1 */ Console.Write(num1++);

/// }

/// </code>

/// </remarks>

[Test()]

[Ignore("NotImplemented")]

public virtual void While0()

{}

}

 

posted on Wednesday, September 01, 2004 12:20:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [3]