Jul 28 2010

Test-Driven Development – From Painful to (Near) Zero Friction

Category: .NET | TestingMatt @ 14:26

I don’t like development friction.  I especially don’t like testing friction.   Over the last several years, my approach to test-driven development and the style of test cases I create has changed drastically in an effort to eliminate testing frication.  To illustrate, I’ve created my first ever screencasts.  In these screencasts, I use TDD to implement a class in RageFeed.  Starting with very coarse, high-friction unit tests, I’ll show you how you can gradually reduce the friction by creating better tests.  Finally, I’ll show you how easy it is to create clean, readable, specification-style tests in RageFeed today.

Note: I apologize for the limitations of ScreenToaster’s player.  I’m in the process of mirroring the videos elsewhere, and I’ll update the post with links as soon as I get around to doing that.

In these screencasts, you’ll see me use a variety of tools.  They are:

Test-Driven Development - Part 1 (View)

In part 1, I introduce the class I’m going to be implementing, and I use TDD to flesh out the class.  I intentionally create my tests as I would have several years ago (meaning they suck).  From there, I gradually evolve them into a better suite of tests, but there’s still room for improvement.

Test-Drivent Development - Part 2 (View)

In part 2, I leverage some ReSharper templates and some base classes I’ve created in RageFeed to create replace my tests with behavior-driven development style specifications.  The result is (near) zero friction testing.

Downloads

I’ve packaged up the base SpecsFor<T> class as well as my ReSharper templates.  Feel free to use them for whatever you like! 

Download SpecsFor and ReSharper Templates: download

Questions? Comments?

I’m certainly not claiming that what we have in RageFeed is The One Way to do testing in .NET.  It works well for me, but I’d love to hear what others think.  Also, this is my first ever screencast, so please drop me a line and let me know what you liked, what you didn’t like, and what you’d like to see in future screencasts (assuming I actually do more).

Tags:

Jun 30 2010

RageFeed’s Message Bus

Category: .NETMatt @ 16:00

In my recent post about heavy controller actions in RageFeed, I promised to show more details about how the Message Bus pattern was being employed within RageFeed to facilitate the creation of simple, business-logic-free controllers.  Then I got sidetracked with a new job, CodeStock, travel, and life in general. Since then, the message bus in RageFeed has changed quite a bit.  In this post, I’ll show you how the bus looks today and how it’s implemented. 

As a refresher, recall that the controllers within RageFeed were becoming quite bloated, with code resembling the following:

private readonly IRageFeedMembershipProvider _membershipProvider;
private readonly IEmailDispatcher _emailDispatcher;
private readonly IProfileService _profileService;
private readonly IMembershipService _membershipService;

public SignupController(IRageFeedMembershipProvider membershipProvider, 
    IEmailDispatcher emailDispatcher, 
    IProfileService profileService, 
    IMembershipService membershipService)
{
    _membershipProvider = membershipProvider;
    _emailDispatcher = emailDispatcher;
    _profileService = profileService;
    _membershipService = membershipService;
}
...
public ViewResult Activate(string username, string activationToken)
{
    var profile = _profileService.GetForUser(username);

    if (profile == null || profile.ActivationToken != activationToken)
    {
        return View("ActivationFailed");
    }

    var user = _membershipService.GetUser(username);
    user.IsApproved = true;
    _membershipService.UpdateUser(user);

    return View();
}

By applying the message bus pattern, I was able to simplify the controllers to code that looked more like this:

private readonly IBus _bus;
private readonly IAuthenticationService _authService;

public SignupController(IBus bus, IAuthenticationService authService)
{
    _bus = bus;
    _authService = authService;
}
...
public ViewResult Activate(string username, string activationToken)
{
    var result = _bus.RequestReply<ActivateUserRequest,ActivateUserReply>(new ActivateUserRequest { Username = username, ActivationToken = activationToken });

    if (!result.Succeeded)
    {
        return View("ActivationFailed");
    }

    _authService.SetAuthCookie(username);

    return View();
}

While this isn’t a huge simplification in terms of lines of code, the improvements are still significant.  The business logic is gone and safely encapsulated somewhere on the far side of the bus.  Prior to the change, the tests had to setup expectations on mocks for both the profile service and the membership service.  After the change, the tests only need to setup the appropriate response from the bus.

The bus itself is quite simple:

public class MessageBus : IBus
{
    private readonly IMessageHandlerRegistry _registry;

    public MessageBus(IMessageHandlerRegistry registry)
    {
        _registry = registry;
    }

    /// <summary>
    /// Sends a message that doesn't require a response.
    /// </summary>
    /// <param name="message"></param>
    /// <typeparam name="TMessage"></typeparam>
    public void Send<TMessage>(TMessage message)
    {
        var handler = _registry.GetCommandHandlerFor<TMessage>();

        if (handler == null)
        {
            throw new HandlerNotFoundException(typeof (TMessage));
        }

        handler.Handle(message);
    }

    /// <summary>
    /// Sends a message and gets the reply. 
    /// </summary>
    /// <typeparam name="TRequest"></typeparam>
    /// <typeparam name="TReply"></typeparam>
    /// <param name="request"></param>
    /// <returns></returns>
    public TReply RequestReply<TRequest, TReply>(TRequest request)
    {
        var handler = _registry.GetCommandHandlerFor<TRequest,TReply>();

        if (handler == null)
        {
            throw new HandlerNotFoundException(typeof (TRequest), typeof (TReply));
        }

        return handler.Handle(request);
    }
}

It uses a registry to find appropriate command handlers, then dispatches the incoming message to the handler.  For request/reply scenarios, it returns the reply from the handler back to the original caller.  The registry is nothing more than a wrapper around StructureMap:

public class MessageHandlerRegistry : IMessageHandlerRegistry
{
    private readonly IContainer _container;

    public MessageHandlerRegistry(IContainer container)
    {
        _container = container;
    }

    public ICommandHandler<TMessage> GetCommandHandlerFor<TMessage>()
    {
        return _container.GetInstance<ICommandHandler<TMessage>>();
    }

    public IMessageHandler<TRequest, TReply> GetCommandHandlerFor<TRequest, TReply>()
    {
        return _container.GetInstance<IMessageHandler<TRequest, TReply>>();
    }
}

Note: I don’t like the names ICommandHandler and IMessageHandler, they’re going to be renamed soon(ish).

By leveraging StructureMap, command handlers can be automagically registered for the appropriate request/reply types, so adding and subscribing a command handler becomes as simple as creating a class that implements an appropriate interface:

public class CheckEmailAvailabilityHandler : IMessageHandler<CheckEmailAvailabilityRequest, CheckEmailAvailabilityReply>
{
    private readonly IUserRepository _repository;

    public CheckEmailAvailabilityHandler(IUserRepository repository)
    {
        _repository = repository;
    }

    public CheckEmailAvailabilityReply Handle(CheckEmailAvailabilityRequest request)
    {
        var isInuse = _repository.GetByEmail(request.Email) != null;

        return new CheckEmailAvailabilityReply {IsInUse = isInuse};
    }
}

Organizing the business logic this way makes it far easier to create small, reusable, easily-testable, and loosely-coupled nuggets of logic. 

One final note, I’m trying to follow the principles of the “onion architecture” as well as the “folder-per-feature” used by Ayende.  This means that each major feature in RageFeed will have it’s own folder (namespace) within Core, as illustrated below.

FeatureOrganization

I’m still not completely satisfied with this breakdown.  It feels “wrong” to have the messages living side-by-side with the handlers, but according to the onion architecture, it’s fine for the web layer to depend on core.  Even so, I’m considering breaking the message off into a separate namespace or project, but it does make it easier to find what you’re looking for when everything related to the implementation of a feature is contained in a single folder as it is now. If you have suggestions for better ways to organize things, please do share.

If you are familiar with MVCContrib, you should be wondering why I chose to implement my own bus instead of leveraging the bus that’s available in MVCContrib.  I have good reasons for that, but that’s a topic for another day.  In a future post (to be published sometime before the dinosaurs return in 2012), I’ll compare the RageFeed bus with the MVCContrib bus and highlight the pros and cons of each.  Until then, let me know what you think in the comments!

Tags:

May 17 2010

Heavy controller actions? The Message Bus Pattern to the rescue!

Category: .NETMatt @ 15:39

I recently derailed (badly) while working on a simple requirement for RageFeed: new user registration.  We decided to use the baked-in ASP.NET membership and profile providers, and I found myself adding a lot of code to facilitate the registration workflow.  This was a problem in and of itself, but I realized I had a bigger problem when I stopped and looked at the tremendous number of test cases for my controller.  I had drifted so slowly into a bad design that I didn’t even realize it was happening until it was too late.  Fortunately, all was not lost.  A design pattern from the distributed computing domain came to save the day.

RageFeed, the super-secret project that I have been only murmuring about from time to time for the last couple of months, is trudging along slowly.  Most of the infrastructure is in place and working, so work has turned towards implementing real, honest-to-goodness features.  The first thing I tried to tackle was new user registration; after all, what good are features without users to (ab)use them?  Our team decided that we wanted users to be able to get in and “raging” as quickly as possible.  The workflow would be like this:

  • User registers with their E-mail address and is given immediate (restricted) access.
  • A verification E-mail is sent to the user.
  • The user clicks a verification link that redirects to the system.
  • The system prompts the user to create a password.
  • The user is given full access to the system.

Knowing that the baked-in ASP.NET membership and profile providers were fairly rigid and not really all that well matched to ASP.NET MVC, we still naively assumed that we would be able to bend them to meet this non-standard workflow.  That was certainly a mistake in hindsight (which I’ll probably blog about later), but it led a bigger problem: bad code. In my push to “get the frickin’ users in the system”, I had lowered my guard and tried to brute force my way through the story.  I knew things were starting to go awry when the unit tests for the signup controller hit a dozen.  Sure, the user registration workflow is a bit complicated, but most of the complexity is business logic, not something that belongs in the controller. 

If I wasn’t so focused on “get it done, now”, I think I would have realized my approach was flawed from the beginning.  Some of the tests were difficult to write and required setting up expectations on multiple services.  This testing friction is usually a good sign that you need to rethink your approach.  In fact, I’d argue that a controller with more than a couple service dependencies needs to be redesigned anyway.  Coding to interfaces and using dependency injection does eliminate your coupling to concrete types, but the interfaces themselves still introduce coupling, and coupling should be kept to a minimum.

The Problem

Let’s look at the constructor for my original implementation of the SignupController:

private readonly IRageFeedMembershipProvider _membershipProvider;
private readonly IEmailDispatcher _emailDispatcher;
private readonly IProfileService _profileService;
private readonly IMembershipService _membershipService;

public SignupController(IRageFeedMembershipProvider membershipProvider, 
    IEmailDispatcher emailDispatcher, 
    IProfileService profileService, 
    IMembershipService membershipService)
{
    _membershipProvider = membershipProvider;
    _emailDispatcher = emailDispatcher;
    _profileService = profileService;
    _membershipService = membershipService;
}

Yep, it depends on *four* separate services.  At a minimum, this complexity could be hidden behind a facade, but there’s a deeper problem.  You can see it when you look at the Activate action:

public ViewResult Activate(string username, string activationToken)
{
    var profile = _profileService.GetForUser(username);

    if (profile == null || profile.ActivationToken != activationToken)
    {
        return View("ActivationFailed");
    }

    var user = _membershipService.GetUser(username);
    user.IsApproved = true;
    _membershipService.UpdateUser(user);

    return View();
}

See that?  It’s subtle, but it’s there, hiding in plain sight: business logic.  The controller now knows the rules for how a user can be activated (their activation token must match the previously stored activation token) and how to activate them (setting the IsApproved flag to true).  As I was TDDing this method, I created three separate test cases: one to test for a non-existent user (null profile), another for an invalid activation token, and finally one to verify that the user is correctly activated.  Each required at least some setup on the mock services.  This same sort of business logic leak occurred in some of the other signup-related actions, leading to a large test fixture and code that made me cringe. 

The Solution

Instead of containing business logic, my controller action should do nothing more than get data from (or provide data to) the views, and pass it off to the business layer of the system for further processing.  The controller should handle things like user-input validation (via model binding) and determining which view to render, but it shouldn’t make business decisions.  Thinking in very generic terms, the controller should publish a command to the business layer, and something in the business layer that subscribes to the command should process it, returning only the information the controller needs to decide which action result to return.  This is about as loosely coupled as you can realistically get: the controller shouldn’t know (or care) who is processing the command, and the class processing the command shouldn’t care about where the command comes from.

There’s a Pattern For That: the Message Bus. While this pattern has historically been used for communication between applications in a potentially distributed environment, it has gained ground recently as a means of decoupling components within the same physical application.  The MVCContrib project includes a message bus, and numerous blog posts of late have presented various incarnations of this pattern. 

Ignoring how RageFeed’s message bus works, take a look at the revised implementation of the Activate action now:

public ViewResult Activate(string username, string activationToken)
{
    var command = new ActivateUserCommand {Username = username, ActivationToken = activationToken};

    var result = _bus.Send(command);

    if (!result.Succeeded)
    {
        return View("ActivationFailed");
    }

    return View();
}

What was gained?

The action is simpler now, and more importantly, it is completely devoid of business logic.  It just creates the command, sends it, gets the response, and decides which view to render.  No longer is the controller coupled to multiple services, instead it has just a single dependency on the message bus, and that’s it.  The corresponding tests are also simpler: they just need to verify that the expected command was sent, and that the correct view was rendered for both success and failure.  They don’t need to setup expectations on anything except the service bus.  Note that I really didn’t remove any business logic from the system, I just (correctly) encapsulated it in the business layer, leaving the controller free to focus on user interface-related concerns. 

So how does it work?

Good question!  I’ll dive into the details of how the bus is implemented and how the command processor for the ActivateUserCommand is implemented in the next post!  In the meantime, let me know what you think in the comments.

Tags:

May 13 2010

Want to be a better developer?

Category: Best Practices | .NETMatt @ 06:44

I've been trying to put together a link list of things that have helped me improve as a developer over the last couple of years.  This is far from complete, but it's a start.  I'm not saying this is an absolute "you have to know these things" list or that it will work for everyone out there, it's just things I've found to be really helpful for me.  As always, your mileage may vary. 

  • SOLID Principles - These principles have helped me a ton.  They aren't rules to be followed blindly, but I've found that understanding the reasoning behind them and trying to strive for code that adheres to them generally makes things easier (and also more fun) in the long run.  Now when I’m faced with a design choice, I usually ask myself which alternative is more SOLID and go with that.  Be sure to check out the SOLID “motivational” posters over at Derick Baily’s blog.
  • Design Patterns – Certain types of problems tend to recur in software development.  For these, we have design patterns.  Getting a handle on design patterns is something that only comes with practice.  You won’t be able to memorize and recognize even the “core” set of patterns immediately, but over time you will likely find yourself recognizing when to apply them more and more often. I strongly recommend Head First Design Patterns (yes, the code samples are in Java, but the patterns themselves are what’s important, and a C# dev should have no problem following along).  It provides a very good introduction to design patterns.
  • Test Driven Development – I think a lot of new developers hear “testing” and immediately glaze over, but I actually enjoy practicing TDD.  It doesn’t just help me test my code, it helps me design my code.  That’s a big advantage that a lot of people overlook.  It also gives me confidence that the class I’m creating does exactly what it is supposed to do, and nothing more.  If you aren’t sure how to do TDD, you can watch one of the various TDD Katas online, such as the String Calculator at Roy Osherove’s site or the Bowling Game at ‘Uncle’ Bob’s site. 
  • Resharper 5 - Resharper is essential for doing C# development in my opinion.  Out of the box, it will suggest lots of little things that can help improve your code.  It helped me learn LINQ by offering to convert ugly for/foreach loops into clean, elegant LINQ expressions, and it finally convinced me that ‘var’ isn’t always evil. 
  • NHibernate and FluentNHibernate - I prefer NHibernate to Castle ActiveRecord these days; the ActiveRecord pattern isn't as flexible or as extensible as an implementation of the repository pattern based on NHibernate, and I’ve run face first into that wall on more than one occasion.  FluentNHibernate makes it a lot easier to get up and running with NHibernate since it hides the XML and provides other nice helpers to get you started.  
  • Lambda expressions - These are essential when working with C# 3.0 or later.  They're a bit hard to grasp at first, but they open up very interesting re-use possibilities, and lots of APIs leverage them heavily. FluentNHibernate uses them to setup mappings, and StructureMap uses them for its embedded Domain-Specific Language (DSL). 
  • Generics - This is an older C# feature, but understanding generics is still just as essential today as ever.  Beyond leveraging the built-in generic classes from the base-class library, learning to wield generics also opens up new avenues for creating clean, extensible, and reusable classes.
  • StructureMap (including its AutoMocking container) - One of the biggest "lightbulb" moments I've had recently was adopting StructureMap and IoC-everywhere.  This totally changed how I code.  Now when I realize a class I'm working on is going to need some other 'service' to fullfill its responsibilities, I simply create a new service interface and add it to my class's constructor.  This makes doing top-down development much easier.  Once I’ve finished the tests and implementation for the class I’m working on, I can turn my attention to creating the class that fullfills the service interface. 
  • LINQ - A lot of people focus on LINQ to SQL, but LINQ is more than that.  LINQ to Objects is incredibly useful. Instead of complicated foreach loops that filter or project objects, I find myself writing short, elegant LINQ queries instead. Be sure you learn about all the various extension methods and keywords, including things like ‘select…into’ and ‘let’. 
  • Moq – Mocking frameworks allow you to configure stubs or fakes that you can substitute for dependencies while testing your classes.  While they can indeed be abused, they are still quite useful.  Moq is my personal favorite for its fluent, lambda-based syntax.  Combine it with the adapter pattern, and you can even use it to fake or stub dependencies on base-class library types.
  • ASP.NET MVC and MVCContrib – If you are going to make an ASP.NET application, do yourself a favor and go the MVC route.  While the drag-and-drop appeal of WebForms can be hard to resist, you will inevitably find yourself fighting its leaky abstractions and lack of flexibility as your application scales.  Out of the box, ASP.NET MVC is still quite bare-bones, and you may find yourself having to focus on issues that are more “plumbing” and less “application”.  Be sure to check MVCContrib before you start reinventing the wheel.  With things like portable areas, fluent control builders, test helpers, and a slew of HtmlHelper extensions, it’s surprisingly easy to build maintainable, testable ASP.NET applications by leveraging MVCContrib and ASP.NET MVC. 

Aside from that, I also follow numerous blogs on development.  If I had to trim Google Reader down to only two dev blogs, they would probably be:

  • Ayende @ Rahien – Creator of more open-source .NET software than probably anyone, Ayende is one of my “code heroes”.  I’ve learned a lot from his blog and by reading the code of his various projects.
  • Los Techies – The number of really smart people blogging here makes it a must-read.  I’ve absorbed a lot of new ideas and information from this place.  

I’m sure I’m overlooking something.  Let me know what you’ve found most helpful in improving your developer chops in the comments.

Tags:

Mar 11 2010

Two things missing from C#

Category: .NETMatt @ 08:07

While building some ugly code to walk the Lucene.NET Query graph, I found myself needing two bits of functionality from C# that it sadly doesn’t provide.  There are arguments for and against each of these, but they certainly would have saved me some pain today.

Switching off of System.Type

The Lucene query graph is a nasty beast.  There’s an abstract base Query class, but no common way to iterate through the graph and extract criteria.  Instead, you have to process each concrete type separately.  An easy way to do this would be to use a switch statement off of the concrete query type and execute the corresponding logic to process the type.  Unfortunately, the C# switch statement only supports types that are convertible to Integer (and strings).  There are solutions, such as this, but why isn’t it built in to the framework?  Peter Hallam explains the reasons, but I don’t agree with most of his argument. Visual Basic’s equivalent of a switch statement allows for case statements to “overlap”, and it doesn’t seem to be causing catastrophic problems there.  I think it’s actually quite intuitive to expect that only the first matching case statement would be executed.  In any case, I’d love to see this added to C#.

Using ‘yield return’ to directly return an IEnumerable

The ‘yield return’ statement is incredibly useful, but I’ve found myself on multiple occasions using it to enumerate a hierarchical object graph.  In such situations, it’s quite annoying that I can’t just ‘yield return’ the entire child object IEnumerable list at once.  Instead, I have to manually iterate the child list and ‘yield return’ each result individually.  I see no reason (at all) why this extra step should be necessary.   Wes describes a possible way to implement this feature, and there’s a (closed as won’t fix) issue on Microsoft Connect with a slew of votes.

Tags:

May 7 2009

Simplified unit testing for ASP.NET MVC JsonResult

Category: MVC | .NETMatt @ 01:45

There are quite a few examples floating around on the web that describe how to test your JsonResult objects to make sure the data was correctly packaged.  They all follow the same basic pattern: mock out core ASP.NET objects (such as ControllerContext, HttpResponse, and HttpContext), call JsonResult.ExecuteResult, recover what was written to HttpResponse.Output, and deserialize it.  Sure, this approach works, but in the same manner as cleaning your house out by lighting it on fire.  It’s way overkill.  There’s a much easier way.  For simple objects, just cast JsonResult.Data:

   1: string value = "Hello, there!";
   2:  
   3: JsonResult result = new JsonResult { Data=value };
   4:  
   5: //SURPRISE!
   6: Assert.AreEqual(value, (string)result.Data);

Yeah, that seems fairly obvious.  You don’t even need the explicit cast there, I just threw it in to prove the point.  But what about anonymous types?  Easy:

   1: var value = new { Id=5, Something="Else" };
   2:  
   3: JsonResult result = new JsonResult { Data=value };
   4:  
   5: IDictionary<string,object> data = new RouteValueDictionary(result.Data);
   6:  
   7: Assert.AreEqual(5, data["Id"]);
   8: Assert.AreEqual("Else", data["Something"]);

See, easy! “But what about arrays of anonymous types?!?!?” Do not fret, LINQ to the rescue:

   1: var values = new[]
   2:                  {
   3:                      new { Id = 5, Something = "Else" },
   4:                      new { Id = 6, Something = "New" },
   5:                      new { Id = 7, Something = "Old" },
   6:                  };
   7:  
   8: JsonResult result = new JsonResult { Data = values };
   9:  
  10: IDictionary<string, object>[] data = ((object[]) result.Data).Select(o => new RouteValueDictionary(o)).ToArray();
  11:  
  12: Assert.AreEqual(5, data[0]["Id"]);
  13: Assert.AreEqual(6, data[1]["Id"]);
  14: Assert.AreEqual(7, data[2]["Id"]);
  15: Assert.AreEqual("Else", data[0]["Something"]);
  16: Assert.AreEqual("New", data[1]["Something"]);
  17: Assert.AreEqual("Old", data[2]["Something"]);

Again, easy!

Alright, I know what you’re thinking.  “But Matt, the other solutions are all way more complicated, plus you’re cheating, that isn’t what JsonResult.ExecuteResult is going to do!” Well, you’re half-right, the other solutions are way more complicated, but this is actually simulating precisely what ExecuteResult will do.  Don’t believe me?  Pop it open in Reflector, or just browse the source (man I love Subversion).  It isn’t doing anything magical, it’s just using JavaScriptSerializer.  My solution just cuts out the middle man and doesn’t require you to mock out a bunch of complicated objects.

Tags:

Mar 18 2009

First Impressions of Resharper 4.5

Category: .NETMatt @ 03:05

Well, I broke down and installed the new beta of Resharper a few minutes ago.  This was motivated by the fact that I was working with our gigantic DAL, and 4.1 was really slowing me down (like it always does on large files).  Resharper 4.5 didn’t boast improvements for large files, just large solutions, but I thought I’d try it anyway. 

So, first thing I notice is that the solution (about 50 projects) opens slightly faster, maybe.  It was really too close to tell without using a stopwatch.  Color me not impressed. 

Next, my Agent Smith plug-in was gone.  It’s a really handy plug-in, so I checked the site, saw that there was a version for 4.5, uninstalled my old 4.1 version of the plug-in, installed the 4.5 version, and thought I would be good to go.  WRONG.

Resharper puked on load with this error: Could not load type
'JetBrains.UI.Shell.PluginSupport.PluginDescriptionAttribute' from
assembly 'JetBrains.Platform.ReSharper.UI, Version=4.5.1182.15,
Culture=neutral, PublicKeyToken=1010a0d8d6380325'
.  Looks like Agent Smith doesn’t work with the beta.  Fortunately, someone has already posted fixed binaries here.

Now, all seems well.  I load the DAL back up, but I’m very disappointed to see that performance has not improved much.  Even typing in such a large file causes all kinds of slowness.  It appears to be a little better than 4.1, but it’s hardly noticeable.

Oh well, I still love Resharper.  It’s a great product.  I guess I just expected/hoped for a little more out of a release that was focused on improving performance.

Tags:

Jan 6 2009

Service DashBored: easily monitor your application's health

Category: .NETMatt @ 02:08

James Kolpack has posted a new project and article on CodeProject for monitoring the health of various resources.  Thanks to it's use of dependency injection, the Service DashBored is easily extensible, so if one of the built-in end points isn't sufficient for your scenario, you can easily write your own.  And yes, he meant to spell it that way. 

Tags:

Dec 16 2008

Unit Testing in .NET Part 3 - Asserting That Your Code Rocks

Category: .NET | Best Practices | TestingMatt @ 07:52

In the previous entries in this series, you've learned about the basics of unit testing, and you've seen how to create a very basic unit test.  In this post, you will learn how to fully use NUnit's Assert class to create a full suite of unit tests.  This post builds off the sample described in the previous post, so be sure to check it out if you want to follow along.

Asserting Equality

In the last post, you saw one example of how to use the Assert.AreEqual method to verify that two objects are equal.  As you will soon see, most methods on the Assert class have a ton of overloads.  You can think of the method as having two levels of overloads: the first for all the various types you could pass in (it has specific overloads for most primitive types as well as more generic versions that work with anything that derives from object), and the second level for controling the message that is shown when the Assert fails.  The type-based overloads are self-explanatory and are handled by the compiler for you automatically, so we'll ignore those and focus on the overloads that look like Assert.AreEqual(expected,actual,message) and Assert.AreEqual(expected,actual,message,params).  Let's incorporate one of these overloads into our unit test from the last post.  Here's the original, unmodified test:

   1: /// <summary>
   2: /// Verifies that the balance increases
   3: /// by the appropriate amount.
   4: /// </summary>
   5: [Test]
   6: public void Deposit_AddsValueToBalance()
   7: {
   8:     Account account = new Account();
   9:     //account.Balance is currently zero.
  10:     account.Deposit(100);
  11:   
  12:     Assert.AreEqual(100, account.Balance);
  13: }

Let's change our assumption about what the Deposit method should be doing.  Let's say that this is an awesome bank that automatically adds a 10% match to anything that you deposit.  We could just change the first parameter to Assert.AreEqual to 110, but what happens if we run that test?  All you will see is the 'expected (110), actual (100)' message.  It doesn't tell you much about why 110 was expected.  That's where the third parameter comes in handy:

   1: /// <summary>
   2: /// Verifies that the balance increases
   3: /// by the appropriate amount.
   4: /// </summary>
   5: [Test]
   6: public void Deposit_AddsValueToBalance()
   7: {
   8:     Account account = new Account();
   9:     //account.Balance is currently zero.
  10:     account.Deposit(100);
  11:  
  12:     Assert.AreEqual(110, account.Balance, "Deposit bonus was not applied!");
  13: }

Now when you run the test, you will see the helpful message that was supplied as the third parameter to AreEqual.  The fourth parameter, a params array of objects, behaves like the String.Format method: the third parameter becomes a format string, and the fourth parameter is the set of values to insert into the format string.  This could be useful for logging additional information about the unit test failure.

For both double and float types, the AreEqual method has an additional set of overloads that look like Assert.AreEqual(expected,actual,tolerance).  The tolerance parameter allows you to tell NUnit how close two floating-point values have to be in order to be considered equal.  Going back to our Deposit_AddsValueToBalance test, what if the bonus wasn't *quite* 10%, but was more like 9.75989%?  Well, we could calculate exactly what the bonus would be and pass that in as the expected value, then apply it, or we could specify a tolerance of 0.01 and leave the expected value as 110, like so:

   1: /// <summary>
   2: /// Verifies that the balance increases
   3: /// by the appropriate amount.
   4: /// </summary>
   5: [Test]
   6: public void Deposit_AddsValueToBalance()
   7: {
   8:     Account account = new Account();
   9:     //account.Balance is currently zero.
  10:     account.Deposit(100);
  11:  
  12:     Assert.AreEqual(110, account.Balance, 0.01, "Deposit bonus was not applied!");
  13: }

In addition to primitive types, NUnit has some "special" support for Arrays and Collections.  Typically in the .NET world, Equality is determined by an object's Equals method. Derived types are responsible for overriding that method if they wish to define equality as anything other than the default behavior inherited from the object class.  NUnit fudges this definition a bit for Collections and Arrays: two collections (or arrays) are considered equal if they have the same number of items and all their corresponding elements are equal. 

There is a corresponding inverse method to AreEqual called (not surprisingly) AreNotEqual.  The obvious difference is that AreNotEqual verifies that two objects are different from one another.  AreNotEqual has the same set of overloads as its complementary method.

Asserting Sameness

Next up is the AreSame method.  You may be wondering "what's the difference between 'same' and 'equal'?".  Objects A and B are equal if A.Equals(B) returns true.  Remember that by default all objects inherit an Equals method from the base object class, and that derived classes can implement custom equality checks as needed, so the exact definition of equal depends on what you are comparing.  'Same' is much simpler: objects  A and B are the same if they point to the exact same object in memory. 

The difference between 'equal' and 'same' may sound a bit confusing if you aren't comfortable with the concept of pointers and object references, so check the documentation here if you are still unclear.

To demonstrate this difference, let's create a new method that looks up account information and verify that repeated calls to the method return the same account information instance.  NOTE: I am intentionally not doing things in a test-driven manner right now.  I don't want to muddy the waters with trying to explain that concept at the same time I'm explaining the asserts.  A proper treatment of test-driven development is coming Real Soon(tm)!

First, let's add some new properties to our Account class along with an overloaded Equals method:

   1: /// <summary>
   2: /// A bank account.
   3: /// </summary>
   4: public class Account
   5: {
   6:     #region Public Properties
   7:  
   8:     /// <summary>
   9:     /// The ID of the account.
  10:     /// </summary>
  11:     public int AccountID { get; private set; }
  12:  
  13:     /// <summary>
  14:     /// The name of the account owner.
  15:     /// </summary>
  16:     public string Owner { get; private set; }
  17:  
  18:     /// <summary>
  19:     /// The current account balance.
  20:     /// </summary>
  21:     public float Balance { get; private set; }
  22:  
  23:     #endregion
  24:  
  25:     #region Public Methods
  26:     
  27: ----Snip----
  28:  
  29:     /// <summary>
  30:     /// Compares the current object to the specified object.
  31:     /// </summary>
  32:     /// <param name="obj"></param>
  33:     /// <returns>True if the accounts have the same AccountID,
  34:     /// false otherwise.</returns>
  35:     public override bool Equals(object obj)
  36:     {
  37:         Account account = obj as Account;
  38:  
  39:         if (account == null)
  40:         {
  41:             return false;
  42:         }
  43:         else
  44:         {
  45:             return AccountID == account.AccountID;
  46:         }
  47:     }
  48:  
  49:     /// <summary>
  50:     /// When you override Equals, you have to override
  51:     /// GetHashCode, too...
  52:     /// </summary>
  53:     /// <returns></returns>
  54:     public override int GetHashCode()
  55:     {
  56:         return AccountID.GetHashCode();
  57:     }
  58:  
  59:     #endregion
  60: }

Next, let's add a method to look up and return a 'dummy' Account object on demand:

   1: /// <summary>
   2: /// Gets the specified account.
   3: /// </summary>
   4: /// <param name="accountID"></param>
   5: /// <returns></returns>
   6: public static Account Lookup(int accountID)
   7: {
   8:     return new Account {AccountID = accountID, Owner = "John Doe"};
   9: }

Finally, let's create our test:

   1: /// <summary>
   2: /// The Lookup should return the exact same instance
   3: /// for all lookups on a specific ID.
   4: /// </summary>
   5: [Test]
   6: public void Lookup_ReturnsSameInstance()
   7: {
   8:     Account account = Account.Lookup(1);
   9:  
  10:     Assert.AreSame(account, Account.Lookup(1));
  11: }

Go ahead and build the project and run the test.  What happened?  The test failed because even though we are returning an identical object for both calls, we aren't actually returning the same object.  Let's correct that by storing some static dummy Account instances; we'll return one of these instead of creating a new instance from now on:

   1: /// <summary>
   2: /// These are our dummy accounts.
   3: /// </summary>
   4: private static Account[] mAccounts = new Account[]
   5: {
   6:     new Account{ AccountID = 1, Owner = "John Doe" },
   7:     new Account{ AccountID = 2, Owner = "Jane Doe" }
   8: };
   9:  
  10: /// <summary>
  11: /// Gets the specified account.
  12: /// </summary>
  13: /// <param name="accountID"></param>
  14: /// <returns></returns>
  15: public static Account Lookup(int accountID)
  16: {
  17:     //Arrays are 0-based, accountIDs are 1-based, so we shift them.
  18:     return mAccounts[accountID - 1];
  19: }

Build and re-run the test, and you should get a success message.

Similar to the AreEqual method, the AreSame method has a logical inverse: the AreNotSame method. 

Asserting Greatness

NUnit includes four methods (with overloads) for asserting various inequalities: Greater, GreaterOrEqual, Less, and LessOrEqual.  The intent of these methods should be obvious, but they differ in one major one from the other assertions we've seen so far.  Recall that the basic versions of both AreEqual and AreSame took an expected argument first and the actual value second.  Applying that same logic, you might expect that expressing the inequality x is greater than y would look like Assert.Greater(y,x), but it's actually the opposite.  I can't tell you how many times I've seen this inconsistency bite developers; it doesn't help that the parameters have less-than-helpful names, like arg1 and arg2.  I don't know why they couldn't have used something more obvious and intuitive, like maybe left and right...

Enough complaining, Let's write some code!  Let's add a new deposit to our account class called RandomDeposit.  This method is very different from our standard Deposit method.  Instead of depositing the specified amount, RandomDeposit will deposit a random amount that is anywhere from 0.5 to 1.5 times the specified amount.  The method looks like so:

   1: /// <summary>
   2: /// Deposits a random amount that is between 0.5 
   3: /// and 1.5 times the specified amount.
   4: /// </summary>
   5: /// <param name="amount"></param>
   6: public void RandomDeposit(float amount)
   7: {
   8:     Random rand = new Random();
   9:     double multiplier = rand.NextDouble();
  10:  
  11:     Balance += (float)(amount*(0.5 + multiplier));
  12: }

Because of the randomness in the method, it's going to be very hard to write a unit test using the Assert.AreEqual method.  Instead, we'll use the GreaterOrEqual method to assert that the deposited amount is at least 0.5 times the amount we deposited.  Here's the unit test:

   1: /// <summary>
   2: /// The method should deposit between 0.5 and 1.5
   3: /// times the specified amount.
   4: /// </summary>
   5: [Test]
   6: public void RandomDeposit_DepositsExpectedAmount()
   7: {
   8:     Account account = new Account();
   9:  
  10:     account.RandomDeposit(100);
  11:     Assert.GreaterOrEqual(account.Balance, 50);
  12:     Assert.LessOrEqual(account.Balance, 150);
  13: }

If you aren't already building and testing by habit, go ahead and build the project and run the new test. 

Asserting Typeiness (If Steven Colbert can do it, so can I!)

The Assert class includes methods for asserting things about the type of an instance.  You can check whether or not an object is of a given type using the IsInstanceOfType method.  The first parameter is the expected type of the object, the second parameter is the actual object.  Let's make our Account class implement the ICloneable interface, then write a test to verify that our clone actually is of type Account:

   1: /// <summary>
   2: /// A bank account.
   3: /// </summary>
   4: public class Account : ICloneable
   5: {
   6: ----SNIP----
   7: /// <summary>
   8: /// Clones the current account.
   9: /// </summary>
  10: /// <returns></returns>
  11: public object Clone()
  12: {
  13:     return new Account {AccountID = AccountID, Balance = Balance, Owner = Owner};
  14: }
  15: ----SNIP----
  16: }

Here's the corresponding test case:

   1: /// <summary>
   2: /// Verifies that a complete clone of the account
   3: /// is returned.
   4: /// </summary>
   5: [Test]
   6: public void Clone_ReturnsAccountClone()
   7: {
   8:     Account account = Account.Lookup(1);
   9:  
  10:     object clone = account.Clone();
  11:  
  12:     Assert.IsInstanceOfType(typeof (Account), clone);
  13: }

The IsInstanceOfType and IsAssignableFrom methods are very similar.  Under the covers, they're just calling the corresponding members of the System.Type class.  Check the documentation on MSDN if you are curious about the subtle differences between the two methods, but for the most part, you can use them interchangeably. 

As with most assert methods, there are various overloads of both IsAssignableFrom and IsInstanceOfType.  Each also has a set of complementary Not methods: IsNotAssignableFrom and IsNotInstanceOfType.

Asserting Nothingness

Sometimes the right result is a null result.  Let's look again at our Account.Lookup method.  Right now, we're not really handling the case of an account ID that doesn't exist.  Let's modify the code so that it returns null when given an invalid account ID:

   1: /// <summary>
   2: /// Gets the specified account.
   3: /// </summary>
   4: /// <param name="accountID"></param>
   5: /// <returns></returns>
   6: public static Account Lookup(int accountID)
   7: {
   8:     if (accountID < 1 || accountID > mAccounts.Length)
   9:     {
  10:         return null;
  11:     }
  12:  
  13:     //Arrays are 0-based, accountIDs are 1-based, so we shift them.
  14:     return mAccounts[accountID - 1];
  15: }

And let's write a new test case to verify this:

   1: /// <summary>
   2: /// The lookup should return null when given an ID
   3: /// that doesn't correspond to an account.
   4: /// </summary>
   5: [Test]
   6: public void Lookup_ReturnsNullForInvalidId()
   7: {
   8:     Assert.IsNull(Account.Lookup(0));
   9:  
  10:     Assert.IsNotNull(Account.Lookup(2));
  11: }

Here we've used the Assert.IsNull method.  This is a very simple assert: it simply checks that the parameter is null.  Like everything else, it has a complementary method that will test that something is not null. 

Asserting Truthiness (or Falsiness)

Everything we've asserted so far could actually be expressed using one of the most basic assertions: IsTrue.  This method asserts that a boolean input is true.  It has a complementary IsFalse method that can be used to assert that an input is false.  These methods can be used to test anything that you can express as a boolean condition.  Let's rewrite our previous Lookup test using only IsTrue instead of IsNull to see this:

   1: /// <summary>
   2: /// The lookup should return null when given an ID
   3: /// that doesn't correspond to an account.
   4: /// </summary>
   5: [Test]
   6: public void Lookup_ReturnsNullForInvalidId()
   7: {
   8:     Assert.IsTrue(Account.Lookup(0) == null);
   9:     //Assert.IsNull(Account.Lookup(0));
  10:  
  11:     Assert.IsTrue(Account.Lookup(2) != null);
  12:     //Assert.IsNotNull(Account.Lookup(2));
  13: }

The test should produce identical output because it is logically equivalent to the original.  You might be tempted to just say "forget about all these other asserts, I'll just use IsTrue for everything!", but that's a terrible idea.  The various other assertions give you a lot more information when something goes wrong than IsTrue will.  For example, if GreaterThan fails, it will tell you the values of both parameters.  If you expressed the test using only IsTrue, you would get a very unhelpful message that says "Expected: True, Actual: False".  Sure, you can probably work backwards, add some logging, etc, to figure out what's going on, but why not use the more powerful GreaterThan method to begin with?

Asserting Failuriness

Sometimes you just want a test to fail. Maybe the test isn't finished, or the test couldn't perform some setup correctly, or maybe you need to test for something that is beyond what the built-in assertion methods can handle.  Assert.Fail to the rescue!  Calling this method will instantly fail a test (assuming you haven't done anything silly like wrapped the call with a try-catch block, which we will look at in a future post). 

Asserting Exceptioniness

We've tested that things work so far, but how do we test that things explode?  Right now, there's nothing in our Deposit method that prevents us from depositing negative amounts.  Let's add some logic to throw an exception:

   1: /// <summary>
   2: /// Deposits the specified amount.
   3: /// </summary>
   4: /// <param name="amount"></param>
   5: public void Deposit(float amount)
   6: {
   7:     if (amount <= 0)
   8:     {
   9:         throw new ArgumentOutOfRangeException("amount", amount, "Must be greater than zero.");
  10:     }
  11:  
  12:     Balance += amount;
  13: }

Error-handling code is good, but it still needs to be tested.  NUnit has the ExpectedException attribute that you can use to verify that an exception is thrown, but I hate this attribute.  What the attribute is really doing is verifying that something somewhere in your test case is throwing an exception, not that the exception is actually coming from where you want it to come from.  Instead, I prefer to go with this model:

   1: /// <summary>
   2: /// The method should throw an ArgumentOutOfRangeException
   3: /// if you pass in a negative value.
   4: /// </summary>
   5: [Test]
   6: public void Deposit_ThrowsExceptionOnNegativeAmount()
   7: {
   8:     Account account = new Account();
   9:  
  10:     try
  11:     {
  12:         account.Deposit(-100);
  13:         //The following line will only be executed if the Deposit method
  14:         //failed to throw an exception.
  15:         Assert.Fail("Expected ArgumentOutOfRangeException was not thrown!");
  16:     }
  17:     catch (ArgumentOutOfRangeException)
  18:     {
  19:         //Ok, this is an expected exception.
  20:     }
  21: }

It requires a bit more code, but this version verifies that the correct type of exception is thrown in exactly the right spot.

Other Ways to Assert RoXXorness

The methods we've looked at so far are just the ones that I have found myself using often over the last several years.  NUnit includes other methods that you can use to assert various things about your objects, including:

  • Assert.Contains - Given an object and a list, this method asserts that the collection contains the specified object.
  • Assert.IsEmpty - Given a collection (or a string), asserts that the object contains no items.
  • Assert.IsNaN - Both double.NaN represent the 'not-a-number' condition (often caused by division by zero).  You can test for this condition using the IsNaN assert.

There is even more...

Recent versions of NUnit have added additional utilities, asserts, etc. to simplify your testing.  You can find out more about them here.  We might look at those in a future post, but I really don't find myself using most of them in my day-to-day testing, and I think most developers can get by just fine without them.

In the next post in this series, we'll look at some more complicated testing scenarios as well as common testing problems and strategies for overcoming them.

Tags:

Dec 3 2008

I declare victory for C# over C!

Category: .NETMatt @ 10:32

Alright, that's not quite fair, but anyone that assumes that C# is going to be slow just because Java is making a big mistake.  One of my classmates made this mistake, and it should have cost him $5, but I chickened out and wouldn't take the bet.  Anyway:

We had a programming assignment to find the average number of colors to color a graph.  I won't go into the details, but suffice to say that we had very similar solutions in terms of algorithmic design (in theory my algorithm should have been faster, but it looks like its advantage is minimal in practice), and he thought his program would smoke mine due to our choices in language and platform.  I chose C# and .NET 3.5 running on Windows, he chose straight-up C running on MacOS.  We both ran our programs on MacBook's with identical processors.  Even *I* expected the C program to win out.  When I use .NET, I know that I am giving up some performance in exchange for an improved development experience... or so I thought.

We fired up our programs in dramatic fashion, then waited for them to complete.  10 minutes later, we had our winner: C# had completed the task ahead of C.  The C program wrapped up around the 14 minute mark.  I love C# and .NET, and though I expected C# to be close to C, I never expected it to be faster. 

Despite the results, I still think the C version should have been faster; there must be some minor algorithmic, implementation, or environment difference that is causing the results.  Still, this does demonstrate that C# is no slouch on the performance front.

Oh, and for anyone that likes Java: I talked to people who implemented the same assignment using Java, and their programs took *hours* to run for the same problem size.  Suck on that, Java! :P

Tags: