Wednesday, 26 December 2007

An article on writing templated WPF custom controls

This is something that we had to discover with reflector when I wrote the Excel-like control we used for the National Express WPF application, so it's good to see people writing about it, especially when it's Charles Petzold in msdn magazine.

An additional thing you might want to do is have properties defining the templates for different sub-elements used by defining a dependency property of type DataTemplate. You may also want to create new sub-controls, e.g. a CellPresenter, that you can add to the template to define where in the template other components of your control will get injected.

That should probably be an article in its own right. Maybe this weekend if I recover from my sore throat.

Tuesday, 25 December 2007

Merry Christmas

While some would consider Christmas as a catholic feast, I'll consider myself the Santa Claus, Christmas tree, tinsels, balls, presents and big dinners as having no fundamental Christian ties. It's a pagan feast and as such, merry Christmas to all men on earth, whatever their religion.

Friday, 21 December 2007

XamlPadX V3.0

Lester just announced (well, on Wednesday but I have a big backlog because I spend my time reading the alt.net chat) XamlPadX 3.0. I know we didn't use the tool on my previous WPF projects, but I think it's the only XAML quick and easy tool that has seen an update recently. Will need to have a play during the festive season!

Thursday, 20 December 2007

As a follow-up on the mocking issue

Over there on CodeBetter.com, David Hayden has posted something about Model-View-Presenter that is a typical example of the confusion I was talking about in my post on why mock frameworks suck.

The interface wasn't mocked, what David did was to create a test double (a fake or a stub depending on how you look at it, but not a mock!) using a mock framework. Again, I don't object on the use of the mock framework (see my previous entry as to where my objection is), but I think we're muddying the water for everybody if we don't get the semantics correct.

Or am I really the only one thinking you should use the right tool for the right job?

Sunday, 16 December 2007

Why Mock frameworks rock

Ayende just commented on my post about writing delegate-based test doubles. He  rightfully highlights that through the method I've described, it becomes clunky to write interaction testing. I'll quote my previous post.

To sum it up, mocks are used when you want to test how your object interacts with another object, that's interaction testing, whereas all the others are used when you want to actually test your object's functionality

Let's forget the discussion about the value of interaction testing and mocks in general for a second. If you do decide to test how your object interacts with one of its dependencies, you're writing a mock and then using a mock framework makes sense. The API used will let you test the interaction conditions much faster than writing code. For example, making sure Initialize() is called only one, you'd have to write a fake using the following.

[Test]

public void InitializeIsCalledOnce()

{

    FakeConfigurationProvider provider = new FakeConfigurationProvider();

    int callCount = 0;

    provider.Initialize = () => { callCount++; };

 

    ClassThatDoesSomething obj = new ClassThatDoesSomething(provider);

    Assert.AreEqual(1, callCount);

}

As you can see, it's entirely doable, but it's starting to get a bit clunky.

The only reason why you wouldn't want to use a mock framework to do such interaction testing is when your dependency is provided by someone that provided a test harness.

Maybe that's where one day we'll be, with developers of a component providing you with a pre-written fake that, based on configuration, will throw at you any possible error combination, and check in which order and how often you called methods for each use-case you have. We're not there yet (or at all) but providing a component and a test harness for the users of that component seems to me a more long-term solution.

There is the question of the intrinsic value of interaction-based testing. In some cases, it is a requirement, in others it's not. Let's say my component has an Initialize() method. What is its behavior when you call it twice? It could be that the object is reinitialized transparently (if it has no side efects), or it could be that the object throws when initialization has already been done. In the second case you don't need a mock. In the first one your tests will catch any introduced error for any non-trivial task (lost a transaction, file handle gone). You could check that an Insert method only calls the repository class twice. But if you test a select after an insert and you get back two objects, you have a failing test.

The interesting question is, what if you don't detect an error, and the Insert method is idempotent. I'd have a tendency to think that those conditions, where you use an object in the wrong way and obtain the right results are probably of lower priorities than other tests. I'd never suggest you shouldn't test that, I'd suggest that writing those tests have probably lower priority than tests in the rest of the system.

Finally, in my last post I highlight the fact that writing your double using delegates, you can provide a default implementation that reacts the way you want, and you can replace the call with specific code on a per-test basis. I'd argue that in those conditions Mock frameworks will have a harder time providing the same level of features. Do you really want to redefine your mock every time? Do you really just want your mock to throw or return a simple value?

The point of my previous post was to suggest that Mock frameworks are over-used and not leveraged for what they are really good at. And they really shine when the objects you depend on don't have a behaviour that lets you receive errors when the caller is not respecting the documentation: done in the right order / too often, etc.

Mocks are a great tool, but shouldn't be used all the time as a general solution to writing tests. You have to pick the right tool for the right job.

Thursday, 13 December 2007

Why Mock frameworks suck, and how to write delegate-based test doubles

There is a big rift in test-oriented developers about when or how to use mocks, what the difference between a mock, a stub, a fake and a dummy is, and what mock frameworks bring to the game. I won't bore everyone with my explanation of the differences, Martin Fowler is well known for formulating patterns better than anyone else, so I'll point you to his Mocks aren't stubs article. I'll also point to Roy Osherove that has a much more simplified entry about the topic titled Mocks and stubs - The difference is in the flow of information.

To sum it up, mocks are used when you want to test how your object interacts with another object, that's interaction testing, whereas all the others are used when you want to actually test your object's functionality, which I'll consider to be unit testing. Interaction testing depends on more than one area of expertise as it involves your mock being called, and because I don't consider the mock part of the unit, I'd argue that you're not testing a unit.

In the case where you write the code from the ground up, I strongly believe there is no real reason to use mocks, as you can bake dependency injection, interfaces and fakes in your API from the ground-up. When trying to put old code under test however, mocks are a valid approach.

image The gray area is when you want to replace one of your dependencies and use a mock framework to implement a fake. Let's take an example that's quite common, abstracting configuration information. Your first step would be to implement an interface that wraps the initialisation and the property you want to retrieve, which we'll call IConfigurationProvider.

One way I often see being employed is using a Mock framework to do the heavy lifting of implementing the code. As such you'll often see code that looks like the following.

IConfigurationProvider provider = Mocks.DynamicMock<IConfigurationProvider>();
 
Expect.Call(provider.ContentLocation).PropertyBehavior();
Expect.Call(provider.Initialize()).IgnoreArguments().Throw(new ConfigurationException());

My main issue with code like this is the use of a domain language to write code. You see, what you're doing is providing an implementation of an interface, but rather than write the code, we use a mock to write... Well, code. Let's see what it takes to write a fake implementation.

public class FakeConfigurationProvider : IConfigurationProvider
{
    public string  ContentLocation
    {
        get { return null; }
    }
 
    public bool  Initialize()
    {
        throw new ConfigurationException();
    }
}

Obviously that's much more code. Or is it? Let's see a character count:

  • Mock code
    • Characters (no space): 220
    • Characters (with spaces): 260
  • Fake code
    • Characters (no spaces): 163
    • Characters (with spaces): 220

As you can see, what seems at first to be a more compact syntax is actually more verbose. Furthermore, you use an API to write code. I'd say that writing a fake using a mock framework is as useful as writing your unit tests by using reflection.

PS: I'm no Rhino expert and I expect someone to give me a more compact syntax if there's one so I can update this code.

Some people will argue that you can use the Stub<T> method with RhinoMocks to achieve the same with less code. I'd reply that creating my FakeConfigurationProvider once will ensure the same logic implementation is used in every single test that leverage the fake. To which mock fanatics will reply that you will want to change the implementation of one method for a specific test, and my way of writing fakes will create a new class for each test.

So here's my response, and the trick I use very often when writing my tests. We'll use a .net feature that doesn't get used very often, explicit interface implementation, coupled with delegates. For each of the methods in my class, I'll declare a delegate, a public property of the delegate type, together with a value (the default implementation), and finally I'll explicitly implement the interface and call the delegate property. Code speaks better than prose, so here it is.

public class FakeConfigurationProvider : IConfigurationProvider
{
    // Delegate types
    public delegate void InitializeDelegate();
    public delegate string get_ContentLocationDelegate();
 
    // Defining fields for our delegates
    public InitializeDelegate Initialize = delegate { return; };
    public get_ContentLocationDelegate get_ContentLocation = delegate { return null; };
 
    // Implementing our interface
    bool IConfigurationProvider.Initialize()
    {
        Initialize(); // calls the delegate!
    }
 
    string IConfigurationProvider.ContentLocation
    {
        get { return get_ContentLocation(); }
    }
}

Note that by default I don't do anything on Initialize. We'll inject the exception throwing later.

This fake is made up of more code, but the flexibility and clarity gains in your tests is enormous. To proove it, let's create a quick object that uses our configuration provider.

public class ClassThatDoesSomething

{

    public string ContentLocation { get; private set; }

 

    public ClassThatDoesSomething(IConfigurationProvider provider)

    {

        try

        {

            provider.Initialize();

            ContentLocation = provider.ContentLocation;

        }

        catch (ConfigurationException) { }

    }

}

And now let's write a test for the default case where everything goes according to plans in our Initialize method and nothing throws.

[Test]

public void CreatingTheClassSucceeds()

{

    FakeConfigurationProvider provider = new FakeConfigurationProvider();

    ClassThatDoesSomething obj = new ClassThatDoesSomething(provider);

    Assert.IsNotNull(obj); // will never be null anyway, keeping the Assert for more obvious expressiveness

}

As you can see if you run this test, the default implementation of my fake for that method doesn't throw. Now let's see how we can change this to throw exceptions. I've used C# 2.0 delegate notation, with the C# 3.0 notation commented out.

[Test, ExpectedException(typeof(ArgumentException))]

public void CreatingTheClassFailsWhenExceptionIsThrown()

{

    FakeConfigurationProvider provider = new FakeConfigurationProvider();

    provider.Initialize = delegate { throw new ArgumentException(); };

    // C# 3.0 Syntax is shorter:

    // provider.Initialize = () => { throw new ArgumentException(); };

 

    ClassThatDoesSomething obj = new ClassThatDoesSomething(provider);

    Assert.IsNotNull(obj); // will never be null as if something throws we won't reach the assert

}

It only took me one line of code to redefine the implementation of my method. Best of all, I use C# to implement my code rather than use the RhinoMock API. Better yet, I can reuse my default fake implementation to be a fully functional in-memory object that reacts as expected, and inject exceptions in any of the methods of my fake object, which is much more reusable. Even better yet, I'm still enjoying compile-time checks that are not applied with any mock framework.

As someone once said, when I see Mocks being used, I reach for my revolver. You've learned already that the test is written in C#, you know your documentation is (primarily) your tests, now learn that code that replaces code is better done in code!

Thursday, 6 December 2007

IE8 is coming?

Off to bed. But before going, a question... Are we going to see IE8 being announced soon?

Tuesday, 4 December 2007

While on the subject of MacBook Pro

If your DVI output resolution is limited, Apple has finally released a new nvidia driver. You can find it here:

Boot Camp 2.0: Video issues with Windows Vista or XP

How to wipe Mac OS out of your MacBook

What an eventful week. As I sit here waiting for countless installs on my VM to get MCMS up and running, I thought I'd take the time to blog about my beloved MacBook Pro.

As some of you already know, I tried really hard when I got my second MBP to like MacOS. I ran exclusively on it for a while, and was running everything under Parallel, and then on Fusion.

The combination of lack of Aero, my mostly windows exclusive world, and with all its bad things the comparatively fantastic outlook (albeit I didn't try entourage), I switched back to full time bootcamp on vista.

After a while though, I realized that no amount of uninstall would reduce my Mac OS partition size, and keeping gigs and gigs of used space around just for the occasional firmware update got me thinking, why am I keeping Mac OS around at all? And as I installed on my main OS way too many beta and alpha of different products, it was time for a big cleanup.

So here's the steps I followed to be running a Vista only MacBook Pro.

  1. Install Bootcamp 2.0 from the Leopard DVD. Follow the steps to burn the drivers CD and let it repartition your drive.
  2. Reboot with the Vista install CD.
  3. Don't install anything, go to the recovery console (on the first screen, instead of Install now use the repair bit.
  4. When you're in the console type diskpart to start the disk management utility.
  5. Wipe the whole drive completely, removing every volume and partition (yes that includes the EFI partition, but so far I've not seen any benefits in keeping it around, considering the very poor EFI use being done on the Mac).
    You do this by either select drive 0 and clear, or select partition n and delete override until none is left.
  6. Once all the partitions are removed, convert your drive to MBR by doing a select drive 0 and convert mbr
  7. Restart the machine and go through the installation screen. When asked to select your drive, do not create anything on it, just select the unreserved space and let Vista do the rest.

Bootcamp is actually several components:

  • An update to provide a legacy BIOS for non EFI-aware OSs.
  • A partition manager with dynamic resizing of HFS+ partitions and NTFS / FAT partition creation capability, with a dual GPT / MBR partition synchronization.
  • An install applet that runs the previous two
  • A set of drivers packaged by Apple, and containing Apple and other vendros drivers in one big install.

Now I think there's one point that's not been explained much. The reason why you convert your disk to MBR in my earlier point is because GPT is not supported as the boot partition for windows. It's a bit of a pain point to figure it out, and when you switch to MBR you won't be able to install Mac OS on that drive again. The way to make both coexist is to provide both a GPT and an MBR on the drive. The mac partitioning utility supports that, and if you run another tool like Partition Magic you may be able to make everything coexist.

As for me, I don't need or use Mac OS, and finally got all my software installed.

I wonder if using hacks I've seen published here and there, I could run Mac OS in MS Virtual PC? Or maybe install it on an external USB Hard drive?