# Tuesday, July 13, 2004

Following the PropertyGrid and the XmlSerialization addin, this addin displays the control classes inside Reflector.

The addin is desesperately simple: if the selected class inherits from System.Windows.Forms, the addin instanciate it and adds it to the window.

posted on Tuesday, July 13, 2004 1:39:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]

This is a preview of a new Reflector addin to well let you search for Program Patterns in your assemblies. The addin is mainly an adaptation to .Net of the article from Santany Paul and Atul Prakash, "A Framework for Source Code Search using Program Patterns".

What are Program Patterns ?

In their article, the authors use a pattern language to specify high-level patterns for making queries on the source code. It smells like regular expression but it operates on statements and expression instead of strings. The basic pieces of the pattern languages are:

  • # describes any expression,
  • @ describes any statement,
  • more to come here...

More specific patterns, like if, while, throw,  are also defined. In fact, for each interface of the Reflector.CodeModel namespace, a corresponding pattern class is needed. Let's illustrate this with a simple example of query: Find all occurence of a if followed by a throw statement.
In the original paper notation, the pattern is defined as follows:

if (#) throw #;

Of course this will have to change a bit for C#.

C# implementation

In my implementaiton, the IPattern interface defines a Program Pattern:

public interface IPattern
{
    bool Match(Object target);
}

The interface is intentionaly simple to enable great extensibility. This interface is then specialized for IStatement, IExpression, IBlockStatement, etc.. For example, the pattern to match a throw statement will be implemented as follows:

public class ThrowExceptionStatementPattern : StatementPattern
{
    // pattern for the expression that is throwed. Pats is a helper class
    private ExpressionPattern expression = Pats.AnyExpression;
    ...

    public override bool Match(IStatement statement)
    {
        // trying to cast statement to IThrowExceptionStatement
        IThrowExceptionStatement th = statement as IThrowExceptionStatement;
        // did not cast, no match
        if (th==null)
            return false;
        // expression did not match, no match
        if (!this.Expression.Match(th.Expression))
            return false;
        // we have a match!
        return true;
    }
}

To ease up things, a helper class containing static methods (Pats) takes care of creating those objects.

Implementing the example

Implementing the example is now just a matter of putting the pieces together. We need a pattern for the if, one for the throw and a pattern that will recurse in all the statements:

// provided by Reflector
IMethodDeclaration visitedMethod = ...
// if pattern
ConditionStatementPattern ifthen = Pats.If();
// setting the Then pattern
// StatementInBlock says the pattern should be in the IBlockStatement
// Pats.Throw() returns a ThrowExceptionStatementPattern 
ifthen.Then = Pats.StatementInBlock(Pats.Throw());
// a pattern that will recurse all the statements
RecursiveStatementPattern rec = Pats.Recursive(ifthen);

// launching the seach
rec.Match(visitedMethod.Body);

Testing the example

The above pattern has been applied to the following class where 2 methods match the pattern, and 2 do not match it:

public class CodeMatchingTest
{
    public void If(bool arg)
    {
        Console.WriteLine("This method has a if");
        if (arg)
            Console.WriteLine("arg is true");
        else
            Console.WriteLine("arg is false");
    }
    public void Throw()
    {
        throw new Exception();
    }
    public void IfThrow(bool arg)
    {
        if (arg)
            throw new Exception();
    }
    public void IfThrowHiddenInsideWhileLoop(bool arg)
    {
        int i = 0;
        while(i<10)
        {
            if (i>5)
                throw new Exception();
            Console.WriteLine(i.ToString());
        }
    }
}

And the result in Reflector is displayed below. As expected, IfThrow and IfThrowHiddenInsideWhileLoop have matched the pattern.

posted on Tuesday, July 13, 2004 1:38:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [3]

Jamie Cansdale (NUnitAddin) has recently started to use the SSCLI tests to verify the output of Reflector.

"The Shared Source Common Language Infrastructure 1.0  is a compressed archive of the source code to a working implementation of the ECMA CLI and the ECMA C# language specification. This implementation builds and runs on Windows XP, the FreeBSD operating system, and Mac OS X 10.2." says the description. If you download this file, you will see that it ships with tons of tests that are used to test the CLI implementation. Each one of the test classes is to be compiled into a console application that returns 0 if successful, 1 otherwise.... Could we harness those test using a test framework ?

First try: all tests in one assembly

Since each fixture is designed to be compiled as a console, we just need to look for classes with a static Main method, load them and execute the main method. This is rather optimistic because it assumes that you can compile all the tests into a single assembly and then load, which is not true because a lot of classes are duplicated and clashes. Anyway, I managed to load some of them "just for fun":

Second try: dynamic compliation

Jamie was ahead of me and had already the solution. He designed a bunch of helper classes that dynamically load the files, compile, and execute them. This combined to a CodeSmith template that would generate a huge fixture (one case per file), he had this harnessed for NUnit. Jamie is kind of "shy" (sorry Jamie) and does not want to write about the amazing stuff he is doing with testing. So if you want to know how he managed to wrap up SSCLI tests in NUnit in a record time, give him a shout ! 

That's all for today, I'll have to modify MbUnit to integrate Jamies work... 

posted on Tuesday, July 13, 2004 1:37:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]

How do you handle the inclusion of examples into your C# documentation ? If you've been asking yourself this question, here's a quick tip for automatic example inclusion.

Let's start with an example. Consider the following dummy class MyClass:

public class MyClass
{
 ...
}

We hapilly write anexample for the MyClass class in a separate xml file (say Doc.xml):

<doc>
  <examples>
    <example name="example1">
       public class MyLibrary
       {
           public static Main(string[] args)
           {
               MyClass mc = new MyClass();
           }
       }
    </example>
  </examples>
</doc>

Now the way Visual Studio suggests uses to include the example is to use the include tag with a XPath expression similar to this:

//< include file='Doc.xml' path='example[@name="example1"]' />

This is fine but it can break easily.Moreover, assuming that you have a lots of examples, you may miss some example that could be integrated into the documentation.

A much better solution is to use the power of XPath. In fact, what we want to include is all the examples that involve the MyClass class, which in XPath translates to: contains(descendant-or-self::*,'MyClass'):

/// <include 
///     file='MyLibrary.Doc.xml' 
///     path='//example[contains(descendant-or-self::*,"MyClass")]'
/// />

That's it. Instead of using name=... you stop worrying and let XPath find the proper examples for you.

posted on Tuesday, July 13, 2004 1:36:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]

I was waiting for this moment for a long time: we have matrix algebra package for .NET!

dnAnalytics home page: http://www.dnanalytics.net/

posted on Tuesday, July 13, 2004 1:36:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [2]

From Benjamin blog;

BOF001: James Newkirk on Integrating Unit Testing into the Software Development Lifecycle.

James Newkirk leading the Unit Testing BoFJames Newkirk lead a Birds of a Feather session on Test Driven Development.  The room was packed to the rafters, showing that Unit Testing is starting to reach a critical mass.  Here are my notes on the discussion from the session which covered how to write tests, how to use tests against legacy systems, how to test against the database and many other topics.

Should we write test code against interfaces or something more abstract than the implementation?
James mentioned that MbUnit is a tool that allows you to test against an interface.  The question was whether you should create interfaces that enable tests to be written against them in case further implementations were created in future.  James' attitude was that this might result in wasted work ('you aint gonna need it') since you may not need it, or may not need it now.  Instead, abstract things out when you need them - don't create an interface just to test it.

James also said that an interface is not a good example of the contract of what is being done - it is the name of the method with input and outputs, but does not reflect how the method reacts to the input. James writes tests that show the real interaction between someone that calls the code and what it produces.

I must say I'm disapointed to have missed TechEd Amsterdam and this session (It's only a couple hour from Brussels). Aaaaargghhh!

posted on Tuesday, July 13, 2004 1:35:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]

TestFu is a collection of framework that can help the tester to build data generator, state machines, grammars, etc... TestFu v0.1 contains:

I have decided to separate the Production Grammar Framework and the Database Populator Framework from MbUnit so that any user (not only MbUnit users) benefit from those two frameworks.

Download TestFu

posted on Tuesday, July 13, 2004 1:35:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [2]

Download addins

The following post gives a list and a quick description of the Reflector addins I have written. The addins are organized by assemblies.

Configuration Reflector for the addins

All addins are targeted for .Net v1.0.5 and Reflector is compiled agains 1.0.3. This means that you must add/modify the Reflector.exe.config file accordingly to the one contained in the zip file. Please do not send bug reports to Lutz but directly to me or through the MbUnit issue tracking system.

Reflector.Graph.dll
Addins

Comments
This addin uses QuickGraph and Refly in the background.

Reflector.Graph.Drawing.dll
Addins

Comments
Might still be a little buggy. Intensive on system resources.

Reflector.Goodies.dll
Addins

Comments
Be aware that this addins actually loads the assembly with Reflector and it will lock those assemblies.

Reflector.TreeMap.dll
Addins

Comments
This addin depends on the TreeMap control from Microsoft Research. Make sure you put TreeMapControl.dll and TreeMapGenerator.dll (from Microsoft TreeMap) in the directory of Reflector.

Reflector.Rules.dll (experimental)
Addins

Comments
Does not do much, still under experimentation.

posted on Tuesday, July 13, 2004 1:34:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [18]

Download addins

The following post gives a list and a quick description of the Reflector addins I have written. The addins are organized by assemblies.

Configuration Reflector for the addins

All addins are targeted for .Net v1.0.5 and Reflector is compiled agains 1.0.3. This means that you must add/modify the Reflector.exe.config file accordingly to the one contained in the zip file. Please do not send bug reports to Lutz but directly to me or through the MbUnit issue tracking system.

Reflector.Graph.dll
Addins

Comments
This addin uses QuickGraph and Refly in the background.

Reflector.Graph.Drawing.dll
Addins

Comments
Might still be a little buggy. Intensive on system resources.

Reflector.Goodies.dll
Addins

Comments
Be aware that this addins actually loads the assembly with Reflector and it will lock those assemblies.

Reflector.TreeMap.dll
Addins

Comments
This addin depends on the TreeMap control from Microsoft Research. Make sure you put TreeMapControl.dll and TreeMapGenerator.dll (from Microsoft TreeMap) in the directory of Reflector.

Reflector.Rules.dll (experimental)
Addins

Comments
Does not do much, still under experimentation.

posted on Tuesday, July 13, 2004 1:34:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [18]

I have added abunch of classes for database testing  in the TestFu project (Download Now ):

 

·         SqlAdministrator: backup, restore, create or drop  databases, and also some methods on tables, constraints,etc...

·         SqlExplorer: extracts the schema of database to a DataSet

·         SqlFixture: a mini data abstraction layer "TestFixture" oriented

 

Let's see them in action...

 

SqlAdministrator

 

·         Backup  database to a file:

·         Restore a database from a file:

·         Drop a database:

·         Drop a table:

·         Drop a constraint:

·         etc...

 

using System;
using TestFu.Data;

public class Demo
{
    public static void Main(string[] args)
    {
        DbAdministrator admin = new SqlAdministrator("...");    
        
        // backup Northwind
        admin.Backup("Northwind",SqlBackupDevice.Disk,@"c:\Backups\Northwind.bkp");
        
        // drop Northwind
        admin.Drop("Northwind");
        
        // restore Northwind
        admin.Restore("Northwind",SqlBackupDevice.Disk,@"c:\Backups\Northwind.bkp");
    }
}

SqlFixture

The DbFixture (SqlFixture for MsSQL server) can be used as a base class for the fixtures involving database testing:

[TestFixture]
public class DatabaseTest : SqlFixture
{
    public DatabaseTest()
    :base("Data Source=testserver;...","MyTestDatabase")
    {}
    
    [SetUp]
    public void SetUp()
    {
        this.Open();
        this.BeginTransaction();
    }
    
    [Test]
    public void Selec()
    {
        IDbCollection cmd = this.Connection.CreateCommand("select * from anytable",this.Transaction);
        ...
    }
    
    [TearDown]
    public void TearDown()
    {
        this.Close();
    }
}
posted on Tuesday, July 13, 2004 1:34:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [3]