# Thursday, July 22, 2004

New features:

 See latest release page on this blog for the download links

posted on Thursday, July 22, 2004 9:02:00 AM (Pacific Daylight Time, UTC-07:00)  #    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 Wednesday, July 21, 2004 10:37:00 AM (Pacific Daylight Time, UTC-07:00)  #    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 Wednesday, July 21, 2004 10:37:00 AM (Pacific Daylight Time, UTC-07:00)  #    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 Tuesday, July 20, 2004 1:51:00 PM (Pacific Daylight Time, UTC-07:00)  #    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 Monday, July 19, 2004 2:43:00 PM (Pacific Daylight Time, UTC-07:00)  #    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 Monday, July 19, 2004 12:10:00 PM (Pacific Daylight Time, UTC-07:00)  #    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 7:38:00 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [4]
# Sunday, July 18, 2004

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 Sunday, July 18, 2004 9:10:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [10]
# Saturday, July 17, 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 Saturday, July 17, 2004 9:48:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [3]

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

posted on Saturday, July 17, 2004 8:55:00 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [4]