How do you write a parameterized (data-driven) test?
Quick Answer
In xUnit, use [Theory] with [InlineData(...)] for simple constant cases or [MemberData(nameof(Cases))] / [ClassData] for complex ones. NUnit uses [TestCase(...)] or [TestCaseSource]. One test method runs once per data row, and each row shows as a separate result.
In xUnit I mark the method [Theory] instead of [Fact] and add [InlineData] attributes, one per set of inputs, so I can test a dozen boundary cases — zero, negative, max, null — with one method and one assertion. If the inputs are objects or I need to build them, I use [MemberData] pointing at a static property that returns the rows. NUnit's equivalent is [TestCase]. The framework reports each row as its own test, so a failure tells me exactly which input broke.
- Great for boundary testing — one method, rows for min, max, zero, negative, null.
[MemberData]source is astatic IEnumerable<object[]>property/method — use it when the inputs are objects or need computing.- Keep the assertion generic across all rows; if one row needs a different assertion, it's a different test.
[Theory]
[InlineData(0, false)]
[InlineData(17, false)]
[InlineData(18, true)]
[InlineData(65, true)]
public void IsAdult_ReturnsExpected(int age, bool expected)
{
var result = AgeChecker.IsAdult(age);
Assert.Equal(expected, result);
}