static void

Parametrized Tests

Running tests with different data is a nice feature. MsTest is pretty poor here, XUnit is ok, and NUnit has very rich, flexible support.

MsTest

It's called data driven tests in Visual Studio, and needs a Sql database (ugh) or a CSV or XML file source. Tests can't have arguments- you access an instance TestContext (not the static version).

Add an xml file, with Copy to Output Directory=Always

<Products>
  <!-- Copy to Output Directory=Always-->
  <Product>
    <Name>Apple</Name>
    <Price>10</Price>
  </Product>
  <Product>
    <Name>Orange</Name>
    <Price>12</Price>
  </Product>
</Products>

The test has a DataSource attribute.

//it does property injection into this
public TestContext TestContext { get; set; }
 
[TestMethod,
 DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
            "XmlData.xml", // file name
            "Product", // root/element
            DataAccessMethod.Sequential
    )]
public void TestDataDriven()
{
    var name = TestContext.DataRow["Name"].ToString();
    var price = Int32.Parse(TestContext.DataRow["Price"].ToString());
}

NUnit

There are three types of parametrized tests - simple inline tests, using properties and/or helper classes, and theories.

This is inline:

//inline parameters
[Test, Sequential]
public void TestMethod1(
    [Values("A", "ABC")] string value,
    [Values(1, 3)] int expected)
{
    Assert.AreEqual(expected, value.Length);
}
 
[Test] //implicitly [Combinatorial]
public void TestMethod2(
    [Values("A", "ABC")] string value,
    [Values(1, 3)] int expected)
{
    //gets A + 1, A + 3, ABC + 1, ABC + 3
}

You can pull from a method or property (and specify another class)

//pull from a IEnumerable member (maybe in another class)
[Test, TestCaseSource("GetData")]
public void TestMethod3(Product product)
{
    Console.WriteLine(product.Name);
}
 
//or return IEnumerable and yield return new TestCaseData(1, 2);
public IEnumerable<Product> GetData
{
    get
    {
        yield return new Product("Apple", 10);
        yield return new Product("Orange", 12);
    }
}

Theories are similar. Instead of [Test] you have [Theory] and it looks up fields or properties by type with the [Datapoints] attribute.

//enums and bools are automatically generated; others from Datapoint[s] fields
[Theory]
public void TestMethod4(int i, DayOfWeek dayOfWeek) { }
 
[Datapoints]
private int[] _data = new[] { 1, 2, 3 };

XUnit

In XUnit, all parameter tests are [Theory], not [Fact]. In v1 you have to reference xunit.extensions.dll; in v2 it's built in.

[InlineData] is just like NUnit's [Values] attribute, but clearer as it's on the method with sequential mode.

[Theory]
[InlineData("A", 1)]
[InlineData("ABC", 3)]
public void TestInline(string value, int expected)
{
    Assert.Equal(expected, value.Length);
}

In v1 you could also refer to a public static property with [PropertyData("GetData")]. In v2, it can be a public static property or method via [MemberData("GetData")].

[Theory]

[MemberData("GetData")]

public void TestMember(string value, int expected)

{

    Assert.Equal(expected, value.Length);

}

 

public static IEnumerable<object[]> GetData

{

    get

    {

        yield return new object[] { "A", 1 };

        yield return new object[] { "ABC", 3 };

    }

}