Showing posts with label Unit Test Patterns. Show all posts
Showing posts with label Unit Test Patterns. Show all posts

Tuesday, 3 March 2009

Collection Asserts in MSTest (and some more)

Sometime I can miss the obvious.

I've been working with MSTest framework for over a year now and up until today I completely missed the fact that beside the Assert class MSTest framework contains 2 other assert classes :

  1. StringAssert - used for string specific asserts like StartsWith, EndsWith and even support regular expression matching
  2. CollectionAssert - used for collection operation like Contains, AllItemsAreNotNull and the most useful AreEquivalent.

Naturally NUnit also has equivalent classes (which of course I missed as well).

Now the thing that really ticks me off is that I was asked this specific question twice in the last month and gave the wrong answer. Only today after I allocated 2 minutes to actually google it, I found out about it.

Lesson learnt - For all consultant out there, Don't get overconfident about your knowledge. Even if its in you specific area of expertise. Always assume that you are mistaken and double check your answer (especially if your answer starts with "You cant...")

Sunday, 1 March 2009

Sela Open House

Last week I gave at Sela a lecture about Design For testability.  For all those who attended I want to thank you for coming.

For all those who missed it, you might be able to catch it this week (I'll be giving it again at Sela on Tuesday) or if you happen to be located at the north parts of Israel it will be repeated nearer to you on the 25/3.

For everyone else you can get the slides here.

Sunday, 8 February 2009

WPF Testing - Part I

Automating GUI testing is always a tricky business. In fact its so hard that people tend to mark it off as too hard to bother with. I believe however that this observation is not correct.

During one of my consulting gigs I was starting to instruct a new team on the concepts of unit tests and since they working on a real product they actually have some GUI involved (imagine that).If that's not enough they are using WPF as their framework of choice. I on the other side cant claim to be a GUI expert (to say the least) and my hands on experience with actual WPF code is, well, close to nothing.

I couldn't leave it at that, so I invested some time in actually trying to figure out how one can write tests for WPF based GUI. This post (which hopefully will be followed by some more) will demonstrate my finding on the matter.

First scenario I wanted to test was how I can trigger an event using code instead of a person clicking on the GUI. For that (and probably for the following examples as well) I constructed a small application that looks like this:

mainWindow

As you can see for now I have a big empty window with a single button and some text fields, but for now hat will be enough. In order to achieve what I'm doing I'll be using the Isolator framework, and I will try keeping my design as simple as I can (I know that there are many patterns out there that probably reflect a much better design scheme, but I really like to address the pressing need of the common programmer and not resort to fancy designs patterns at this point)

Firing a mocked Event

As I said, first I want to explore how to test an event handler wired to a button. i.e. to simulate a user pressing a button and check that the correct logic is executed. for the purpose of this demo I assume that my GUI is backed up by a business logic layer that will handle the actual business logic, and since that should be tested separately,  all I want for now is to make sure that the proper logic from that layer is called.

so here's the implementation of the business logic:

internal class BusinessLogic
{
void GetResult()
{
throw new NotImplementedException
("no logic yet");
}
}
As you can see noting much in there, in fact since I'm not interested in the buisness layer at this point the implemantation is not yet ready and all i have is a an empty

and here is the the window source code:

public partial class HurtFundsMainWindow : Window
{
public HurtFundsMainWindow()
{
InitializeComponent();
}

private void GetResults_Click(
object sender, RoutedEventArgs e)
{
BusinessLogic logic = new BusinessLogic();
logic.GetResult();
}
}

Again at this point i dont have much, only a simple event handler for the button click action that will delegate all logic into the business layer. Note that i'm not using any dependancy injection pattern and I'm not working against an interface at this point. (my application is so simple that I really don't see the need for doing that. I assume that when the application evolves the need will make me evolve the design as well)

and here is the actual test code:

[TestMethod]
[Isolated]
public void Clicking()
{
//Create the fake business logic and inject it into production code
BusinessLogic fakeLogic =
Isolate.Fake.Instance<BusinessLogic>();
Isolate.Swap.NextInstance<BusinessLogic>()
.With(fakeLogic);

//Create the fake button
Button fakeButton =
Isolate.Fake.Instance<Button>(Members.CallOriginal);
//inject it into production code
Isolate.Swap.NextInstance<Button>()
.With(fakeButton);
//replace the button event wiring
Mock mockButton =
MockManager.GetMockOf(fakeButton);
MockedEvent handle =
mockButton.ExpectAddEvent("Click");

//create the window
HurtFundsMainWindow wind =
new HurtFundsMainWindow();

//fire the mock event
handle.Fire(wind, new RoutedEventArgs());

Isolate.Verify.WasCalledWithAnyArguments(
() => fakeLogic.GetResult());
}

Not very trivial so lets see what's goes on here.

the first step in the test, is creation of the fake business logic, i create the fakeLogic and using the Swap ability I ask the Isolator framework to replace the next created instance of business logic with the fakeLogic (check this for further details).

Second step is doing the same for the button that will be created, after that I also fake the actual event wiring done by WPF and put my hands on a faked handle which I later use to fire the event. (note the event handling is done using an older variant of the Isolator API. I hope that in the near future the proper API will be added to the AAA syntax as well)

Next comes the actual executing. I first create the window, and then I use the fake handle to trigger the event.

At the end of the test I verify that the GUI actually calls the proper logic method (in this case the GetResult() method).



That's all for now, while this is only a basic scenario, the principles shown here can be adapted to handle much of the event system of the WPF system. If you have any questions feel free to leave a comment.

Sunday, 28 September 2008

MSTest – ExpectedException and exception message.

Since this is my first blog post ill start out small enough.

Recently we have migrated our unit test from NUnit into MSTest. Although by large the transition was quite smooth, one of the more annoying issues is the different behavior of the ExpectedException attribute.

An intended design or an oversight by MS?

I would (wishfully) think the latter is the case. But in any case I would say its a Mistake.

In any case, since MsTest does not support asserting on the exception message, we had to revise some of the tests. The revision itself is quite simple, just need to wrap the test code with try catch clause. Something like:

[TestMethod]
public void SomeTest()
{
try
{
//The test code:
//...
//...
Assert.Fail("We should not get here");
}
catch(SomeExceptionType ex)
{
Assert.AreEqual(
"Expected Message",
ex.Message);
}
}

However after doing this for a couple of tests we have managed to come up with a slightly better pattern:

[TestMethod]
[ExpectedException(
typeof(SomeExceptionType))]
public void SomeTest()
{
try
{
//The test code:
//...
//...

}
catch(SomeExceptionType ex)
{
Assert.AreEqual(
"Expected Message",
ex.Message);
throw;
}
}

Although the difference is quite minor, still we found the second version much more expressive and readable.

To conclude, there’s a lesson to be learnt here. When trying to replace a well used framework its best to make sure that the transition will be as easy as possible (Unless you are MS and can get away with this).

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Walgreens Printable Coupons