# Wednesday, September 29, 2004
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]