4

Let's suppose I have some method that returns a IEnumerable<int> object. This methods make use of yield return keyword to produce a infinite sequence. Example of the Fibonacci algorithm :

public static IEnumerable<long> Fibonacci()
{
    long x = 0L;
    long y = 1L;
    long z;
    yield return x;
    yield return y;
    while (true)
    {
        z = x + y;
        yield return z;
        y = x;
        x = z;
    }
}

How can I properly create unit test for such sequence ? By proper I also mean readable.

I can write unit tests like this :

[TestMethod]
public void FibonacciTest()
{
    var actual = MyClass.Fibonacci();

    var @enum = actual.GetEnumerator();

    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 0);
    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 1);
    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 1);
    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 2);
    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 3);
    Assert.IsTrue(@enum.MoveNext();
    Assert.AreEqual(@enum.Current), 5);
    Assert.IsTrue(@enum.MoveNext();
}

This test works, but I don't think it is readable. What are general (Fibonacci alogrithm was only a example) guidelines for writing unit tests for sequences ?

PS: I'm using Visual Studio OOB Test suite + Pex.

Steve B
  • 36,818
  • 21
  • 101
  • 174

2 Answers2

6

How about something like:

[TestMethod]
public void FibonacciFirstSixTest()
{
    var actual = MyClass.Fibonacci();
    int[] expected = { 0, 1, 1, 2, 3, 5 };

    Assert.IsTrue(actual.Take(6).SequenceEqual(expected));
}

By the way, I would point out that you don't really have an infinite sequence there since there are only so many members of the Fibonacci series that can fit in long (or any fixed-size data-type for that matter). You might as well test all 92 of them.

Ani
  • 111,048
  • 26
  • 262
  • 307
  • As I said, Fibonacci was only an example. I have the same method with BigInteger, or other methods like `IEnumerable GetPermutations(T[] source)` that produces a large number of items if not an infinite. Anyways, thanks for the answer. – Steve B Feb 13 '12 at 16:15
4
CollectionAssert.AreEqual(new[] {0,1,1,2,3,5}, MyClass.Fibonacci().Take(6).ToList());
Matt Howells
  • 40,310
  • 20
  • 83
  • 102
  • Never saw `CollectionAssert` before :) This should simplify most of sequence unit test! thx – Steve B Feb 13 '12 at 16:13
  • 1
    @SteveB I didn't down vote, but I think the reason as that the CollectionAssert takes an ICollection (in MSTest). Whereas Take(n) will return an IEnumerable, so that won't actually compile. – RichK Feb 13 '12 at 17:04
  • @RichK: A simple `.ToList()` would have solve the problem. The downvoter should have notify Matt instead of downvote. – Steve B Feb 13 '12 at 19:38