RSS
Facebook
Twitter

Wednesday, August 17, 2011

9 years ago…

August 2002 I’ve started  my first “real” programming job, I was an intern at Intel working side by side with intelligent and talented engineers on a performance monitoring tool for Linux. A lot has happened since, I switched a few jobs, sometimes I worked for big enterprise and sometime for a small startup until I ended up on my current position in a company that is neither (or both).

I wrote software that did video processing, ecommerce and helped people write better unit tests (I hope) mostly (but not only) in C++ and .NET languages where I felt most comfortable.

 

In the last nine years I learnt quite a lot in the since I wrote my first void main - on my first job I leant how to write code, on my second job I learnt how to write code fast but only on my previous job did I learn how to write code well…

In every job and every project I had a the good fortune to find guru that could teach me something and with each lesson I improved not only professionally but also as an individual.

All in all it’s been fun ride, it’s not over - I’m just stopped for a minuet too look back and take a breath.

I can’t wait to see what would happen in the next nine years.

Monday, August 01, 2011

Supercharge Isolate.Verify

At work we use Typemock Isolator for all of our Isolation/Mocking needs. Lately I’ve noticed that my co-workers do not like to use verify. One of the reasons they prefer not to use it is that sometime Verify error messages leave much to be desired. There are a few simple tricks that helps Isolator help you when using verify and I’m going to show them right here in this very blog post.

What is this verify you talk about?

Any Isolation framework worth mentioning can do the following three features:

  1. Create fake object (a.k.a mock/stub/test dummy – you name it)
  2. Set expectations on fake objects
  3. Verify method was called in fake object

Verify is what differentiate mock from stub. Without getting into too many definitions a mock object is a fake object that can assert that methods were called inside of it and even check if it was called with specific arguments.

So what’s the problem with verify?

Verify is a powerful tool and should be used with care. Checking that method A called method B is not its purpose. You don’t want your tests failing just because you did a simple refactoring. Instead Verify should be used when the end result of the test is a method call and not a state, for example use it in a test that an email is sent to the client after a successful operation.

Oddly enough – that’s not the reason that developers tend not to like using it. The real reason is that unlike Assert that provides a clear and understandable message when fails some of the times Verify message is not clear enough. Good errors are crucial when test fails – it saves time by helping the developer understand the issue without needing to debug the code which equals faster development time.

And so we would like to improve the error message on the failing test to help understand why the test failed a few days/weeks/months after it was written.

Improving Verify error messages

Luckily for us the good people of Typemock have already thought about this issue as long as enough information is provided.

[Test]
public void VerifyStringParam()
{
    var cut = Isolate.Fake.Instance<ClassUnderTest>();

    cut.SomeMethod("this is the wrong string");

    Isolate.Verify.WasCalledWithExactArguments(() => cut.SomeMethod("this is the right string"));
}

The code is quite simple even if you’re not familiar with Isolator – in fact it’s too simple, I cannot think of a good reason to write this code other than to show my point.

First we create a fake object then we call a method on it and finally we check that it was called with a different variable.

We got the following error:

 image

The error is exactly what I need – it tells me what went wrong and shows the first offending character in the sting. But what happens if I use a more complex parameter:

[Test]
public void VerifyComplexParam()
{
    var cut = Isolate.Fake.Instance<ClassUnderTest>();

    var myClass = new MyClass
    {
        Id = "wrongId",
        Data = 11
    };

    cut.SomeMethod(myClass);

    var expected = new MyClass { Id = "Id", Data = 5 };
    Isolate.Verify.WasCalledWithExactArguments(() => cut.SomeMethod(expected));
}

Here I use a more elaborate (yet useless) class as a parameter, and again I “accidently” call the method with the wrong parameter. Running the test would provide the following failure message:

image

SO what happened? the test failed but Isolator in his great wisdom offers us to implement Equals because 9 out of 10 times I don’t want to compare the parameters by reference just by their inside value. By implementing equality methods we can tell Isolator if the inside of the class is the same – after implementing Equals I get the following error message:

image

How cool is that! Isolator has used equals and when it failed assumed that one (or more) of the properties of the class are to blame and so it shows all of the properties in MyClass that are not equal.

But what happens if we pass a really complex class – one that contains another class?

[Test]
public void VerifyMoreComplexParam()
{
    var cut = Isolate.Fake.Instance<ClassUnderTest>();

    var complexClass = new ComplexClass
    {
         InnerClass = new MyClass { Id = "id", Data = 10 }
    };

    cut.SomeMethod(complexClass);

    var expected = new ComplexClass
    {
         InnerClass = new MyClass { Id = "Id", Data = 5 }
    };

    Isolate.Verify.WasCalledWithExactArguments(() => cut.SomeMethod(expected));
}

We get this error message:

image

Isolator has found that the problem was the parameter (duh) but he would not tell me what is wrong with it – I guess there is no option but to debug – wrong!

By overriding ToString we can improve the error message into this:

image

Even if Isolator won’t guess what is different between the classes at least he shows the string representation helping me discover for myself why the test failed.

 

You might have noticed that when using these simple tricks you can discover instantly why the test failed – without using debugger or even glancing at the source code – in fact throughout this post I never once showed the code for the class under test.

 

Happy coding…

Related Posts Plugin for WordPress, Blogger...