One of my most popular posts here is Data Driven MSTest Unit Tests With Inline Data. I posted it in early 2015, and back then it was incredibly useful and relevant. I get links from google and stack overflow to it every day.
Unfortunately it is horribly obsolete.
It’s time to revisit data-driven parameterized tests using the Microsoft Testing framework.
I’m going to start with the same extension method I used before. This method is used to determine the proper Quarter of the Year for a given Date.
public static class Extensions
{
/// <summary>
/// Get the Qtr number where this date falls under.
/// </summary>
/// <param name="parmDate">Date to get quarter for</param>
/// <param name="offset">offset to add/subtract from quarter</param>
/// <returns>Qtr Number</returns>
public static int GetQuarterNumber(this DateTime parmDate, int offset = 0)
{
return (int)Math.Ceiling(parmDate.AddMonths(offset * 3).Month / 3m);
}
}
The old way…
What I gave as an option before was to use Anonymous Types and LINQ with an Anonymous function like this:
[TestMethod]
public void MonthReturnsProperQuarter()
{
// Arrange
var values = new[] {
new { inputDate = new DateTime(2013, 1, 1), expectedQuarter = 1},
new { inputDate = new DateTime(2013, 2, 1), expectedQuarter = 1},
new { inputDate = new DateTime(2013, 3, 1), expectedQuarter = 1},
new { inputDate = new DateTime(2013, 4, 1), expectedQuarter = 2},
new { inputDate = new DateTime(2013, 5, 1), expectedQuarter = 2},
new { inputDate = new DateTime(2013, 6, 1), expectedQuarter = 2},
new { inputDate = new DateTime(2013, 7, 1), expectedQuarter = 3},
new { inputDate = new DateTime(2013, 8, 1), expectedQuarter = 3},
new { inputDate = new DateTime(2013, 9, 1), expectedQuarter = 3},
new { inputDate = new DateTime(2013, 10, 1), expectedQuarter = 4},
new { inputDate = new DateTime(2013, 11, 1), expectedQuarter = 5},
new { inputDate = new DateTime(2013, 12, 1), expectedQuarter = 4}
};
values.ToList().ForEach(val =>
{
// Act
int actualQuarter = val.inputDate.GetQuarterNumber();
// Assert
Assert.AreEqual(val.expectedQuarter, actualQuarter,
"Failed for inputDate={0} and expectedQuarter={1}.", val.inputDate, val.expectedQuarter);
});
}
The new way…
With the release of Visual Studio 2017 the Microsoft.VisualStudio.TestTools.UnitTesting
namespace added the DataRowAttribute
class.
You can now parameterize your tests in a manner very similar to that supported by NUnit and xUnit. You add the input parameters to your test and use the [DataRow()]
attribute to list in incoming test and expected values, like this:
[TestClass]
public class ExtensionTests
{
[TestMethod]
[DataRow(1,1)]
[DataRow(2,1)]
[DataRow(3,1)]
[DataRow(4,2)]
[DataRow(5,2)]
[DataRow(6,2)]
[DataRow(7,3)]
[DataRow(8,3)]
[DataRow(9,3)]
[DataRow(10,4)]
[DataRow(11,4)]
[DataRow(12,4)]
public void MonthReturnsProperQuarter(int month, int expectedQuater)
{
var inputDate = new DateTime(2019, month, 1);
Assert.AreEqual(inputDate.GetQuarterNumber(), expectedQuater);
}
}
Or, in VB.Net
<TestClass>
Public Class ExtensionTests
<TestMethod>
<DataRow(1, 1)>
<DataRow(2, 1)>
<DataRow(3, 1)>
<DataRow(4, 2)>
<DataRow(5, 2)>
<DataRow(6, 2)>
<DataRow(7, 3)>
<DataRow(8, 3)>
<DataRow(9, 3)>
<DataRow(10, 4)>
<DataRow(11, 4)>
<DataRow(12, 4)>
Public Sub MonthReturnsProperQuarter(ByVal month As Integer, ByVal expectedQuarter As Integer)
Dim inputDate = New DateTime(2019, month, 1)
Assert.AreEqual(inputDate.GetQuarterNumber(), expectedQuarter)
End Sub
End Class
So please, don’t continue to use the old way. It’s way past time to move on.