Monday, April 19, 2010

Unit testing random methods

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/unit_testing_random_methods.htm]

You can unit test random methods by running the method in a loop and checking for statistical results.

For example, say you have a method to return a random integer between 1 and 10 (this could just as easily be to return any type between any range). You could run the test 100,000 times and confirm that the statistical distribution makes sense. With a sufficient sample size, there should be at least one of each value. The mathematically advanced could apply better statistics, like checking the proper distribution.

Here's a simple sample. It runs the random method in a loop, and checks just that each value was returned at least once.

public class MathHelper
{
    private static Random _r = new Random();

    public static int GetRandomInt()
    {
        //return Random int between 1 and 10
        //recall that upper bound is exclusive, so we use 11
        return _r.Next(1, 11);
    }
}

[TestMethod]
public void Random_1()
{
    int iMinRandomValue = 1;
    int iMaxRandomValue = 10;

    //Initialize results array
    //ignore 0 value
    int[] aint = new int[11];
    for (int i = iMinRandomValue; i <= iMaxRandomValue; i++)
    {
        aint[i] = 0;
    }

    //Run method many times, record result
    //Every time a number is returned, increment its counter
    const int iMaxLoops = 1000;
    for (int i = 0; i < iMaxLoops; i++)
    {
        int n = MathHelper.GetRandomInt();
        aint[n] = aint[n] + 1;
    }

    //assert that each value, 1-10, was returned
    for (int i = iMinRandomValue; i <= iMaxRandomValue; i++)
    {
        Assert.IsTrue(aint[i] > 0,
            string.Format("Value {0} never returned.", i));
    }

}

Of course, this assumes you're explicitly trying to test the random method - you could mock it out if the method is just a dependency and you're trying to test something else.

No comments:

Post a Comment