views:

113

answers:

5

I have a method that returns an IEnumerable that I want to be able to test. For the test inputs that I will be using, it will return approximately 10 values.

What is the cleanest way to write a test in this situation?

Update:

Many thanks for the answers so far. Several useful suggestions that I am now going to investigate.

I don't think that my original question was very well worded, a better way would have been as follows:

I want to write several tests for a method that returns an IEnumerable of KeyValuePair<string, uint>. For the the sets of test data that I will be using, the method will return only a few values. ~10 values in most cases.

What is the best way of me expressing my sets of expected return values and testing the method in MSTest?

+1  A: 
if(YourMethod(input).Count() != 10) // test failed

The Count extension method works over IEnumerable and should allow you to determine the number of items in the series, if that's all you're after. Just makes sure you're including System.Linq.

Adam Robinson
+1  A: 

If you're using MSTest, as I presume, check out the CollectionAssert class.

You'll have to be more specific than "approximately 10 values", however, if you want to write a proper unit test.

Noldorin
Absolutely. What I was getting at is that for the sets of input data I will be running the tests against, it will only be returning a small number of values as opposed to millions of values.
dbush
Oh, fair enough then. :)
Noldorin
A: 

Not sure what you're getting at, can you clarify?

For me, tests should test expected and unexpected situations. They should test boundary and typical situations.

In your case, I'd be testing null, empty, one entry and more than one entry (say, your typical ten). You'll know the code that's generating the IEnumerable so you should be able to decide what other boundaries there are.

serialhobbyist
I've updated the original question.
dbush
+3  A: 

Assuming you know what results should be returned, I find Enumerable.SequenceEqual useful. (Create an array with the expected results.)

In MoreLINQ I've wrapped this in an extension method which will test for equality and dump out both sequences if they're not equal. Actually, the MoreLINQ tests are mostly about testing for equality of sequences, so they may give you some handy examples :)

Jon Skeet
Thanks for your very useful answer.
dbush
+1  A: 

I find the lack of asserts for IEnumerables unfortunate in CollectionAsserts.

I therefore created the following:

internal static class EnumerableAsserts
{
  public static void AreEqual<T>(
      IEnumerable<T> expected, 
      IEnumerable<T> actual)
  {
    AreEqual(expected, actual, null);
  }

  public static void AreEqual<T>(
    IEnumerable<T> expected, 
    IEnumerable<T> actual, 
    string text)
  {
    text = text == null ? "" : text +" : ";
    if (expected == null)
      Assert.Fail("{0}expected is null!", text);
    if (actual == null)
      Assert.Fail("{0}actual is null!", text);
    if (ReferenceEquals(expected, actual))
      return;
    var e = expected.GetEnumerator();
    var a = actual.GetEnumerator();
    int count = 0;
    while (e.MoveNext())
    {
      count++;
      if (a.MoveNext())
      {
        if (!EqualityComparer<T>.Default.Equals(e.Current, a.Current))
          Assert.Fail(
            "{0}the {1}{2} item did not match expected '{3}' but was '{4}'", 
            text, count, MathUtils.GetOrdinal(count), e.Current, a.Current);
      }
      else
      {
        Assert.Fail(
          "{0}there were {1} expected entries but {2} actual entries",
          text, expected.Count(), actual.Count());
      }
    }
    if (a.MoveNext())
      Assert.Fail(
        "{0}there were {1} expected entries but {2} actual entries",
        text, expected.Count(), actual.Count());
  }
}
ShuggyCoUk