I found a good use for the InlineData xUnit attribute:

public class DateDiffCalculatorFacts
    InlineData("2008-09-25 14:31", "1 minute"),
    InlineData("2008-09-25 15:05", "35 minutes"),
    InlineData("2008-09-25 16:05", "1 hour 35 minutes"),
    InlineData("2008-09-25 17:05", "2 hours 35 minutes"),
    InlineData("2008-09-25 19:05", "4 hours"),
    InlineData("2008-09-25 02:30", "12 hours"),
    InlineData("2008-09-24 00:00", "1 day 14 hours"),
    InlineData("2008-09-23 00:00", "2 days 14 hours"),
    InlineData("2008-09-20 00:00", "5 days"),
    InlineData("2008-08-20 00:00", "1 month 5 days"),
    InlineData("2008-07-01 00:00", "2 months 24 days"),
    InlineData("2008-05-01 00:00", "4 months"),
    InlineData("2007-07-20 00:00", "1 year 2 months"),
    InlineData("2005-07-20 00:00", "3 years")]
    public void Can_get_correct_age_for_date(string dateString, string expectedAge)
        var date = DateTime.Parse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.None);
        var referenceDate = DateTime.Parse("2008-09-25 14:30:00", CultureInfo.InvariantCulture, DateTimeStyles.None);

        var calc = new DateDiffCalculator(date, referenceDate);

        string age = calc.ToString();
        Assert.Equal(expectedAge, age);

This is the first time I have used this style of testing (called RowTests in MbUnit/NUnit). Maybe in this case it is not the right thing to do from a pure TDD perspective as the test name is not very descriptive of what is being tested. If each InlineData was extracted to a sepereate test they could be given more meaningfull names like "Measure_will_be_in_plural_when_more_than_one" and "Skip_sub_measure_when_main_measure_is_higher_than_two". On the otherhand having the test like above made it dead simple and fast to add new test cases and it still quite apparenent what the intended outcome is.


Colin Jack said...

I wouldn't fight it, if combanitorial/parameterized testing suits the situations then I think its right to use it and this seems like a good use.

Jeff Brown said...

This is a good use of a parameterized test.

MbUnit's [Row] attribute allows you to specify a Description for each test so you can include a more descriptive name for each case if you like. I think xUnit.Net and NUnit also support this behavior.

Pete said...

For that test, you might want to look at xUnit's FreezeClock feature - http://agileprogrammer.com/dotnetguy/archive/2007/11/11/23751.aspx :)

Torkel Ödegaard said...

I don't think the FreezeClock feature is that well suited, I need a fixed reference date, otherwise each date in each InlineData argument need to be compensated, it would just complicate things.

Peter Gfader said...

I want to have that in Visual Studio unit tests!!!