Chris Surfleet's MentalReboot

Code insights tinged with a spot of insanity

This post is 95% for my own reference but hopefully it will help out anyone else who is converting large test files to the FluentAssertions syntax.

I have quite a lot of unit test files with long blocks of Assert.AreEqual statements like this:

Assert.AreEqual("1020379", items[0].JobNumber);
Assert.AreEqual("1019579", items[1].JobNumber);
Assert.AreEqual("1019444", items[2].JobNumber);
Assert.AreEqual("1019284", items[3].JobNumber);
Assert.AreEqual("1019173", items[4].JobNumber);
Assert.AreEqual("1018999", items[5].JobNumber);
Assert.AreEqual("1018830", items[6].JobNumber);
Assert.AreEqual("1017968", items[7].JobNumber);
Assert.AreEqual("1017926", items[8].JobNumber);

I'd like to change them all to the xxxx.Should().Be("xxxx) syntax but there are better things to do with my day than pressing copy and paste for an age. So a quick regex replace in Sublime Text and they all get converted for me.

Search regex:

Assert.AreEqual\(("[a-zA-Z0-9]+"), ([a-zA-Z0-9\[\]\.]+)\);

Replace regex:

$2.Should().Be($1);

And we have:

items[0].JobNumber.Should().Be("1020379");
items[1].JobNumber.Should().Be("1019579");
items[2].JobNumber.Should().Be("1019444");
items[3].JobNumber.Should().Be("1019284");
items[4].JobNumber.Should().Be("1019173");
items[5].JobNumber.Should().Be("1018999");
items[6].JobNumber.Should().Be("1018830");
items[7].JobNumber.Should().Be("1017968");
items[8].JobNumber.Should().Be("1017926");

I know it's not the perfect expression (only works for string values, won't catch dodgy characters etc) but it was knocked together in 2 minutes and meant I only had to do some mopping up of the remaining items it failed to match, hopefully it could save someone else some time too.

If anyone has any improvements to the above expression, or any others for converting MsTest to FluentAssertions then please post a comment and I'll get them added to the post.

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



So, I’ve finally got AspectMap open-sourced onto codeplex. It’s been a fairly crazy three months in which I haven’t really blogged or expanded its code base, but that is now hopefully a thing of the past. I have plans for a caching mechanism which I’ll build over the next few weeks, and a few other improvements including a load more unit tests. More than that though, I want to see what you can all do with it! Here’s what I’d like to get from you, the community:

  • I want to see what you guys can do with it. It’s pretty much solved the problems I set out to solve for myself, but this is a big world with a host of different problems. If you build a good aspect then add it to the StandardAspects namespace. If it doesn’t work quite how you’d like then mod it. I’m really keen to see what the community can do with it;
  • Help me manage it. I’ve never run an open source project before so I’m sure I’ll stumble along the way. Tell me what I’m doing wrong (or not doing at all!) or what’s going well;
  • Add items to the issue tracker. I’d love to keep developing the framework, but I need to know what you want from it. Do you want support for other IoC frameworks? Improved speed? Get an issue logged and I’ll get to work.

Thanks everyone, I look forward to seeing where we can take this!

AspectMap on CodePlex

AspectMap on NuGet

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



This is the second of my posts on the brilliant FluentAssertions library. You can find the rest of the posts here:

OK, so today we’ll jump right into the various assertions we can make on dates, times and collections.

Dates and Times

This is where the wonder of FluentAssertions really starts to shine through, DateTime assertions become hugely more readable. Take the simplest example:

Assert.AreEqual(DateTime.Parse("08/10/2008"), myDateValue);

Urgh. This does not read at all well, to start with I’m in the UK but I’m sure a lot of you guys over the pond read that as 10th August. (I know, it could have been written a little better, I’m labouring the point OK?) Let’s try it again:

myDateValue.Should().Be(8.October(2008));

Great, it reads better, and there is no chance of confusion over our intention. How about this:

myDateValue.Should().BeWithin(5.Days()).After(10.January(2010));
I really don’t need to explain what we are asking above which is absolutely brilliant. You can call your product owner over to query how some feature should work, and they can see that you are asking the correct questions – without having to know how to write a single line of c# code.

You can chain your expectations using the And keyword just as you could for strings as well:

myDateValue.Should().BeWithin(5.Days()).After(10.January(2010))
  .And.BeAtLeast(6.Hours()).Before(15.January(2010).At(21, 00));

It’s worth playing around with code completion, but some of the DateTime methods available include: BeBefore, BeAfter, BeWithin, HaveDay/Month/Year/Hour/Minute/Second, BeAtLeast, BeMoreThan.

Collections

Next up there are a few really nice collection assertions. Let’s say you want to ensure that a collection is empty. In MsTest you would write:

Assert.AreEqual(0, items.Count);

You could obviously improve this to:

items.Count.Should().Be(0);

But you can actually write this instead:

items.Should().BeEmpty();

Once again, the language of your assertions is very similar to the natural language used to define acceptance criteria.

Collections is where I find myself chaining assertions the most. You could write something similar to:

items.Should().HaveCount(5)
  .And.NotContainNulls()
  .And.OnlyHaveUniqueItems()
  .And.NotContain(15);

There are a multitude of assertions available for inspecting the contents of your collection. This example wouldn’t work but will show you some the various methods available to you:

items.Should().Contain(new[] {1, 2, 3})
  .And.ContainInOrder(new[] {7, 10})
  .And.HaveSameCount(someOtherCollection)
  .And.NotBeSubsetOf(someOtherCollection)
  .And.ContainItemsAssignableTo<int>();

You can even use predicates:

items.Should().OnlyContain(n => n > 3)
  .And.Contain(n => n > 40);

So the collection should only contain numbers larger than three, and at least one item larger than 40. This isn’t as readable however so I generally tend to create my own custom assertions in these cases, which I’ll go through in part 4 of this series.

So, that’s all you need to know about basic FluentAssertions. I’ll admit to finding this series tricky to write so far as all the code examples are so obvious, but next time we’ll dig into some of the more in depth stuff you can do with exception and event assertions. I’ll finish up in part 4 by describing how you can create your own assertions library to keep your tests clean and readable. Thanks for reading!

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



I recently discovered a very cool project on NuGet – FluentAssertions. This is a really funky little library that vastly improves assertions in your unit tests, whether you are using NUnit or MsTest. I’ve been using it for a few weeks now and thought I would share some of the cool things you can do with this framework. I’ll start with the simple stuff and over the next few weeks show some of the assertions you can make on dates and collections, then exceptions and events and creating your own assertions and using this to map unit tests more closely to acceptance criteria. Some of this will duplicate the documentation on codeplex, but I’ll go into more detail about how to use the techniques in practice.

Firstly, go and NuGet FluentAssertions into one of your test projects. Next go and find some string assertion, which will probably look something like this (I’m using MsTest):

Assert.AreEqual("123,456,789", result);

You can replace this with the following FluentAssertion:

result.Should().Be("123,456,789");

OK, so this already reads much more nicely, which is great, but the reporting of a failed assertion is also improved. If result was the wrong value with the AreEqual assertion you would get the following:

Assert.AreEqual failed. Expected:<123,456,789>. Actual:<123,458,789>.

This is alright, but it could be tricky to notice the 8 which should be a 6. Compare that to the FluentAssertion’s reporting:

Expected string to be
"123,456,789", but
"123,458,789" differs near "8,7" (index 6).

 

Not only have the expected and actual values been lined up vertically to aid scanning, but the message even highlights the point in the string the values differ.

You’ll notice if you type Should() and look at the code completion list that you get a lot of options. You could use StartWith or EndWith, or even do a wildcard match using Match. You can also chain your expectations together using the And property, so instead of:

result.Should().NotBeNullOrEmpty();
result.Should().NotMatch("*,");
result.Should().NotMatch(",*");

You can write:

result.Should().NotBeNullOrEmpty()
  .And.NotMatch("*,")
  .And.NotMatch(",*");

 

This quickly makes your unit tests much more readable.

You can ignore casing easily, so instead of

Assert.AreEqual("hello", result.ToLower());

You can use

result.Should().BeEquivalentTo("hello");

This is just the options available for strings. There are all the options you would expect for numbers too:

result.Should().BeGreaterOrEqualTo(5);
result.Should().BeInRange(2, 27);
result.Should().BeNegative();

The cool thing about these expectations is that they will work for any object implementing the IComparable interface too!

Finally, each expectation can take a reason string too, which will be printed out along with an expectation error:

result.Should().Match("JM*", "because result should be a valid UK insurance number");
Expected string to match "JM*" because result should be a valid UK insurance number,
but "INVALID" does not match.

This is not only helpful when the test fails, but when looking at the test code it reads much more like a set of acceptance criteria, so the intent of your test is more obvious.

I hope this will encourage a few of you to use this great library – next time I’ll go through the things you can do with collections, dates and times, and then get into creating your own custom expectations.

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



This is the fifth, and for now, last, of my series of posts on AspectMap. If you’re new to AspectMap, I’d recommend you start at the beginning and work your way through the tutorials:

Aspect Nesting

This is a fairly easy concept to grasp. When you add an aspect to a method you are wrapping its logic with that of the attribute handler. If you add a second aspect to the same method you are wrapping both the logic of the method and the first attribute handler within the second – nesting them.

We’ll illustrate this with a simple example and a couple of unit tests. Firstly create a new test class:

[TestClass]
public class NestingTests
{
  private static string _output;
}

Notice the _output variable, this will be used to pass information between the aspects and the tests. All the following classes should be created inside the test class. Next up are our attributes and handlers:

public class NestingLevel1Attribute : Attribute {}
public class NestingLevel2Attribute : Attribute {}

public class Level1Handler : AttributeHandler
{
  public override Action<IInvocation> Surround(Action<IInvocation> invocation,
      Attribute sourceAttribute)
  {
    return i =>
    {
      _output += "Level1 Entered\n";
      Console.WriteLine("Level1 Entered");
      invocation(i);
      _output += "Level1 Exited\n";
      Console.WriteLine("Level1 Exited");
    };
  }
 }

public class Level2Handler : AttributeHandler
{
  public override Action<IInvocation> Surround(Action<IInvocation> invocation,
      Attribute sourceAttribute)
  {
    return i =>
    {
      _output += "Level2 Entered\n";
      Console.WriteLine("Level2 Entered");
      invocation(i);
      _output += "Level2 Exited\n";
      Console.WriteLine("Level2 Exited");
    };
  }
}

Nothing complicated, we simply add text to both the _output variable and write it to the console (for ease of testing). Next up a really simple test class:

public interface ITestClass
{
  void DoSomething();
}

public class ItemWithMultipleAttributes : ITestClass
{
  [NestingLevel1]
  [NestingLevel2]
  public void DoSomething()
  {
    _output += "DoSomething\n";
    Console.WriteLine("DoSomething");
  }
}

The DoSomething method just writes to the _output variable, and applies both of our aspects. The final stage of setup is a registry to wire it all together:

public class NestingRegistry : AspectsRegistry
{
  public NestingRegistry()
  {
    ForAspect<NestingLevel1Attribute>().HandleWith<Level1Handler>();
    ForAspect<NestingLevel2Attribute>().HandleWith<Level2Handler>();
    For<ITestClass>().Use<ItemWithMultipleAttributes>().
        EnrichWith(AddAspectsTo<ITestClass>);
  }
}

It’s worth pausing at this point to go through how AspectMap will order your aspects by default. From now on I will use the terms closer and further away for this – closer means that the aspect wraps closer to the source method, further away is at a further remove, wrapping the method and other aspects. All control over this prioritisation occurs in your registry, not in the classes, although I plan to add priorities at this level in a future release.

When writing your ForAspect declarations, those that appear first will be applied closer to the source method. We can confirm this with a test:

[TestMethod]
public void NestingUsesCorrectOrder()
{
  ObjectFactory.Initialize(x => x.AddRegistry(new NestingRegistry()));

  ITestClass testClass = ObjectFactory.GetInstance<ITestClass>();
  _output = "";

  testClass.DoSomething();

  Assert.AreEqual("Level2 Entered\nLevel1 Entered\nDoSomething\nLevel1 Exited\nLevel2 Exited\n", _output);

  ObjectFactory.ResetDefaults();
}

If you run this and look in your results window you should see the following from the Console.WriteLine statements:

Level2 Entered
Level1 Entered
DoSomething
Level1 Exited
Level2 Exited

Prioritising

Great. But what about situations where you’d like to define which aspect has priority? You can control this with the WithPriority method in your registry:

ForAspect<NestingLevel1Attribute>().WithPriority(1).HandleWith<Level1Handler>();
ForAspect<NestingLevel2Attribute>().WithPriority(2).HandleWith<Level2Handler>();

Aspects with a higher priority will be applied closer to the source method. You can confirm this by making the change above and re-running your test. It will fail, but the console will now read:

Level1 Entered

Level2 Entered
DoSomething
Level2 Exited
Level1 Exited

Awesome. You should now have all the skills you need to use AspectMap in any of your applications!

This is it from me on AspectMap for a while – I’ll be concentrating on adding a few new features for a 1.5 release in the fairly near future, and the source will be available on codeplex this week. I’m totally open to input as to what is in this next release so feel free to get in touch on here or through twitter, or even better, get involved when I open source it.  Thanks for reading!

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



After reading this post from Sayed (a great blogger by the way!) I downloaded and installed the VS2010 Web Publish Updates. All was well until I realised that all my WiX projects were now showing as unavailable in solution explorer. The system is failing looking for a .wpp.targets file which does not exist. I've tried all sorts of things including:

  • creating the file it wants (it still thinks it doesn't exist)
  • overriding the publish profile properties in the wixproj file (no change)
  • using alternative targets (no change)

After 4hrs of digging around in the 10.5 targets files I'm drawing a blank on all fronts. I'll keep working on it but in the meantime I'd recommend staying off the upgrade.

If you're a brave soul and want to help me fix this, I'm keeping a question on StackOverflow updated with my attempts, get involved!

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



This is part 4 of my series of posts on AspectMap. If you’re new to AspectMap I’d recommend you start at the beginning and work your way through the tutorials:

What Is Multicasting?

Multicasting is most often associated with networking, where it refers to the delivery of a message to multiple destinations at once from a single source. We are using the same concept here to describe the application of a single aspect to multiple methods, using a single attribute declaration. Let’s skip to an example:

public class AnImportantClass : IDoesImportantStuff
{
  [Auditable]
  public void DoSomething()
  {
    // Does something important
  }

  [Auditable]
  public void DoSomethingMoreImportant()
  {
    // Does something more important
  }
}

We have a couple of methods here, both marked with the AuditableAttribute, which we can wire up in an AspectsRegistry as normal to do some auditing stuff. AspectMap will allow you to wire this up via a single attribute at the class level:

[Auditable]
public class AnImportantClass : IDoesImportantStuff
{
  public void DoSomething()
  {
    // Does something important
  }

  public void DoSomethingMoreImportant()
  {
    // Does something more important
  }
}

This will do the equivalent of applying the attribute to every single method on the class. This works fine for attributes without properties, but what about a scenario this, where you are passing configuration information with the attribute?

public class AnImportantClass : IDoesImportantStuff
{
  [Auditable(15)]
  public void DoSomething()
  {
    // Does something important
  }

  [Auditable(15)]
  public void DoSomethingMoreImportant()
  {
    // Does something more important
  }

  [Auditable(20)]
  public void AnExtraImportantMethod()
  {
    // This requires more detailed auditing
  }
}

You can actually define a default attribute at class level, and then override it on methods which need something more specific:

[Auditable(15)]
public class AnImportantClass : IDoesImportantStuff
{
  public void DoSomething()
  {
    // Does something important
  }

  public void DoSomethingMoreImportant()
  {
    // Does something more important
  }

  [Auditable(20)]
  public void AnExtraImportantMethod()
  {
    // This requires more detailed auditing
  }
}
Quick and easy. I hope all this information is useful to some of you, and the post on nesting and prioritising aspects will be up in the next few days.

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



This is part 3 of my series of posts on using AspectMap – an aspect oriented framework for StructureMap. If you’re new to AspectMap I’d recommend starting at the beginning and working through the series:

In this post we’ll create a retry aspect which will allow you to retry the functionality of a method a specified number of times for a certain exception. For instance you could set a method up to try some SQL operation up to 4 times if it receives timeout exceptions. This will introduce you to the technique for inspecting the attribute that kicked off your handler.

We’ll start with the attribute:

public class RetryAttribute : Attribute
{
  public RetryAttribute(int maxTries, Type targetException)
  {
    MaxTries = maxTries;
    TargetException = targetException;
  }

  public int MaxTries { get; set; }
  public Type TargetException { get; set; }
}

Notice that it has two properties, populated through the constructor. TargetException is the exception which will trigger a retry, and MaxTries is the maximum number of attempts that will be made. This would be specified on a method like this:

[Retry(3, typeof(TimeoutException))]
public void CompleteLongRunningOperation()
{
  // Long running code which could throw a TimeoutException
}

So this will allow two retries of a TimeoutException before finally throwing it. Any other exception will be thrown as usual.

So, how do we implement the handler? Create a new RetryAttributeHandler inheriting from AttributeHandler and put the following code into its Surround method:

if (!(sourceAttribute is RetryAttribute))
  throw new ArgumentException("Unable to handle retries for attribute '" +
    sourceAttribute.GetType() + "'.");

RetryAttribute attribute = (RetryAttribute)sourceAttribute;

Fairly simple, we only want to deal with RetryAttributes. Next comes the important bit:

return i =>
{
  for (int count = 1; count <= attribute.MaxTries; count++)
  {
    try
    {
      invocation(i);
      return;
    }
    catch (Exception ex)
    {
      if (ex.GetType() != attribute.TargetException ||
                   count == attribute.MaxTries)
        throw;
    }
  }
};

We loop until MaxTries, and if an exception is thrown we check if we are on the last try, or the exception is not of the expected type. If so we throw it, otherwise we continue around the loop. The return statement ensures that if invocation(i) run’s successfully that we don’t continue round and do it again!

That’s pretty much it, you wire up your registry just like we did in previous posts:

ForAspect<RetryAttribute>().HandleWith<RetryAttributeHandler>();
For<ITestClass>().Use<MyClass>().EnrichWith(AddAspectsTo<ITestClass>);

One thing which I hope is becoming clear now is that there never seems to be much actual code involved – if you can think of a concern cross cutting enough, it will generally be generic enough to make the coding of it trivial. Which I see as a great thing!

Next up I’ll discuss nesting and prioritisation of handlers, at which point you’ll have all the major skills you need to go out and start creating some really funky stuff. Thanks for reading!

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



Welcome back to my series on using AspectMap – an aspect oriented framework for StructureMap. If you’re new then take a look at the earlier posts on the subject:

In this post I’ll walk you through the setup of a generic exception handler which can be assigned to any code you like with the addition of a single attribute. Let’s get started!

Keeping it generic, the first thing we’ll create is a new interface for handling any exception:

public interface IExceptionHandler
{
  void HandleException(Exception ex);
}

You can create your own implementation of this which can do anything you like, log to Elmah, redirect to an error web page, send an email, whatever. Next we will create a new AttributeHandler called ExceptionAttributeHandler:

public class ExceptionAttributeHandler : AttributeHandler
{
  public ExceptionAttributeHandler(IExceptionHandler exceptionHandler)
  {
    ExceptionHandler = exceptionHandler;
  }

  public IExceptionHandler ExceptionHandler { get; set; }

  public override Action<IInvocation> Surround(Action<IInvocation> invocation,
    Attribute sourceAttribute)
  {
    throw new NotImplementedException();
  }
}

Notice the ExceptionHandler attribute and constructor, which allows us to inject our custom handler via StructureMap. Next, in the Surround method, replace the NotImplementedException with:

return i =>
{
   try
  {
    invocation(i);
  }
  catch (Exception ex)
  {
    ExceptionHandler.HandleException(ex);
    throw;
  }
};

This is just like we did with the LoggingHandler except that this time we’re nesting the invocation call within other code, and farming out the actual logic of what happens when an exception occurs to our custom IExceptionHandler class. After handling the exception, we continue to throw it.

Which is a problem.

Think about it, let’s say you are logging to Elmah and are quite happy to have the application fail after the error is logged. You will get the error logged at every point down your call stack where this aspect is applied, for a single error. We’ll fix this by creating a new HandledException class:

public class HandledException : Exception
{
  public HandledException(Exception innerException) :
    base(innerException.Message, innerException)
  {}
}

And checking the exception type in the catch block of the Surround method:

catch (Exception ex)
{
  if (!(ex is HandledException))
  {
    ExceptionHandler.HandleException(ex);
    throw new HandledException(ex);
  }
  throw;
}

Great, now you’ll handle the exception once, and get a HandledException raised by the application.

All we need to do now is create an attribute to use for the mapping:

public class ExceptionHandleAttribute : Attribute
{}

That is all the handler setup done, but we still need to wire it up to your application. Ensure that your registry inherits from AspectsRegistry and add the following lines, replacing the items in capitals with your own classes:

ForAspect<ExceptionHandleAttribute>().HandleWith<ExceptionAttributeHandler>();
For<IExceptionHandler>().Use<YOUREXCEPTIONHANDLER>();

For<IYOURCLASS>().Use<YOURCLASS>().EnrichWith(AddAspectsTo<IYOURCLASS>);

Now any methods you mark with the ExceptionHandle attribute in YOURCLASS will be automatically handled for you by your IExceptionHandler implementation.

Next time I’ll cover either a code security handler which will go into inspecting the attribute which triggered the handler code, or how to nest and prioritise multiple handlers. If you want one before the other, leave me a message in the comments and I’ll get to it. All the handlers I’m creating here will be included out of the box in a new AspectMap release some point soon too.

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



May
31

AspectMap 1.0 Released

by Chris | Tags:

So that’s it – version 1.0 of AspectMap is on NuGet! This post will very quickly talk about the features available to you in this release, and my ideas for future versions.

What It Is

AspectMap is an Aspect Oriented framework built on top of the StructureMap IoC framework. It allows you to control your cross-cutting concerns centrally, and assign these to methods or classes by marking them with attributes.

Features

  • Aspects are wired up in your StructureMap repository, using an easy, fluent syntax;
  • Custom code will inherit from the AttributeHandler class, which gives access to the calling method and the attribute which launched the call;
  • Aspects can be nested, and the setup syntax allows central control over execution order;
  • Aspects can be assigned to individual methods, or entire classes;

Where to Get It

You can grab it now from NuGet by searching for AspectMap or clicking here.

How to Use It

Upgrading From Version 0.5

Apologies to those of you who downloaded the 0.5 release – I’ve had to make a breaking change for version 1. If you upgrade your NuGet package you will get a compile-time exception on each of your handler classes. This can be fixed in two quick steps:

Firstly inherit your class from the AttributeHandler abstract class rather than the IAttributeHandler interface.

Now change your Surround method declaration to:

public override Action<IInvocation> Surround(Action<IInvocation> invocation,
                   Attribute sourceAttribute)

This overrides the method in the abstract class, and allows you access to the attribute causing the handler to be called. By using an abstract class I can ensure that in future I can add features without changing the Surround method, to avoid more breaking changes.

What Next?

In the coming weeks I hope to firstly concentrate on the how to series of posts, which will also introduce a number of standard aspects you can use ‘out of the box’. After that I’d like to implement some form of caching system to ensure everything runs as fast as possible. All the source code will be on github in the next few days as well, so if you’d like to be involved then that’s brilliant!

Feedback

This project is currently solving the problems I needed solving, but I’d love it to be as useful as possible to you all. It’d be great to hear from you if you have any suggestions, or just stories about what you’ve used it for, it will definitely shape the future of AspectMap, get in touch!

Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link:



Month List

Sign in

Top Programming Sites Vote for me at Fuelmyblog