29/01/2008
I'm moving to http://garryshutler.blogspot.com/ as Live Spaces just doesn't have the features I need. I'm not sure if anyone other than my friend's are subscribing to this, but please change your subscription if you are.
Thanks!
26/01/2008
I'm a great believer in making your unit tests as easy to read and understand as possible. I was thinking about how I could improve my tests the other day and thought about using extension methods to create a more fluent way of creating complex assertions.
This has allowed me to create a complex assertion like:
- testObject.ShouldBeTheSameObjectAs(targetObject).And.ShouldBeEqualTo(testObject).And.ShouldSatisfy(x => x is Object);
Which I hope you'll agree reads a lot easier than those three assumptions on separate lines. Also, note that I have added the ability to use a predicate for when there isn't a method which quite matches your needs.
Here's the code for the extension methods:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using MbUnit.Framework;
-
- namespace UnitTestingExtensions
- {
- public static class FluentTestingExtensions
- {
- public static FluentAnd<T> ShouldSatisfy<T>(this T testTarget, Predicate<T> predicate)
- {
- Assert.IsTrue(predicate.Invoke(testTarget));
- return new FluentAnd<T>(testTarget);
- }
-
- public static FluentAnd<T> ShouldBeEqualTo<T>(this T testTarget, T comparisonObject)
- {
- Assert.AreEqual(testTarget, comparisonObject);
- return new FluentAnd<T>(testTarget);
- }
-
- public static FluentAnd<T> ShouldBeTheSameObjectAs<T>(this T testTarget, Object comparisonObject)
- {
- Assert.AreEqual(testTarget, comparisonObject);
- return new FluentAnd<T>(testTarget);
- }
-
- public class FluentAnd<T>
- {
- public T And { get; private set; }
-
- public FluentAnd(T target)
- {
- this.And = target;
- }
- }
- }
-
- }
And here are the tests for the extension methods:
I'd love to hear some feedback on what you think of this style.

25/01/2008
After seeing Jeffrey Palermo's SmartBag (part 1 and part 2) I was inspired to create my own version which was more specific to my needs. For one I'm a lover of the IEnumerable<T> interface, especially when combined with the power of LINQ for Objects.
Anyway, enough of my waffle, here's the code for the class.
- using System;
- using System.Collections.Generic;
- using System.Collections;
- using System.Text;
-
- namespace SmartBag
- {
- public class SmartBag
- {
- private Hashtable _hashtable;
-
- public SmartBag()
- {
- this._hashtable = new Hashtable();
- }
-
- public void Add<T>(T item)
- {
- List<T> list;
-
-
- if (!this._hashtable.ContainsKey(typeof(T)))
- this._hashtable.Add(typeof(T), new List<T>());
-
- list = this._hashtable[typeof(T)] as List<T>;
- list.Add(item);
- }
-
- public IEnumerable<T> Get<T>()
- {
- if (!this._hashtable.ContainsKey(typeof(T)))
- throw new IndexOutOfRangeException(string.Format("There are no entries for {0}", typeof(T).Name));
-
- foreach (T item in this._hashtable[typeof(T)] as List<T>)
- yield return item;
- }
- }
- }
There are basically two methods to it, Add and Get. Add adds items of the specified type to a list of that type. Get retrieves the list of the specified type.
Below are my test cases which should give you some ideas of how you can use it.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using MbUnit.Framework;
-
- namespace SmartBag
- {
- [TestFixture]
- class SmartBagTest
- {
- [Test]
- public void AClassAddedAgainstAnInterfaceCanBeRetrievedTogether()
- {
- SmartBag bag = new SmartBag();
-
-
- bag.Add<IContract>(new Parent());
- bag.Add<IContract>(new Child());
-
- Assert.AreEqual(2, bag.Get<IContract>().Count());
- }
-
- [Test]
- public void AChildWillBeAddedToItsParentsEnumerationIfYouDefineIt()
- {
- SmartBag bag = new SmartBag();
-
-
- bag.Add(new Parent());
- bag.Add<Parent>(new Child());
-
- Assert.AreEqual(2, bag.Get<Parent>().Count());
- }
-
- [Test, ExpectedException(typeof(IndexOutOfRangeException))]
- public void AnExpectionWillBeRaiseWhenAttemptingToRetrieveATypeThatDoesNotExist()
- {
- SmartBag bag = new SmartBag();
-
-
- foreach (Object item in bag.Get<Object>()) { } // must enumerate for it to be evaluated
- }
-
- [Test]
- public void ShouldBeAbleToAddChildAsADifferentType()
- {
- SmartBag bag = new SmartBag();
-
-
- bag.Add(new Parent());
- bag.Add(new Child());
-
- Assert.AreEqual(1, bag.Get<Parent>().Count());
- Assert.AreEqual(1, bag.Get<Child>().Count());
- }
-
- private class Parent : IContract
- {
- }
-
- private class Child : Parent
- {
- }
-
- private interface IContract
- {
- }
- }
- }
To begin with this is a basic idea. I hope to utilise it in an upcoming project and it will probably look a bit different after I've used it in anger. Something I can see I might need is to extract an interface to make testing easier but I've left that out for now as YAGNI may apply.
Any feedback would be greatly appreciated.
