The DataSource Attribute

You can use the DataSource attribute to call your TestMethod multiple times with different data each time.

Lets say for example I have an order details table like the one in Northwind.

  • OrderId
  • ProductId
  • UnitPrice
  • Quantity
  • Discount

In your application somewhere you have a method that calculates the cost of an item. Given the OrderId and ProductId it will return the Price for that line item. You want to write a test for this method, easy enough.

<TestMethod()> _
Public Sub TotalPriceTest()
Dim price As
Decimal
Dim MyDac As New
MyWindowsApplication.MyDac

    MyDac.Load()
    price = MyDac.getTotalPrice(10329, 38)

    Assert.AreEqual(price, CDec(4005.2))

End Sub

The problem is this test only tests one particular row. What about the case where there is no discount. I guess we have to write another unit test with a different orderId and productId. Hey we could create a file that contains a bunch of variations and then write a loop in the unit test to go through each one.

Or...

We could use a DataSource Attribute along with the TestContext Class.

When you add the DataSource Attribute to a TestMethod it will retrieve all the rows from the table identified for that connection and call your testmethod for each row. Inside your TestMethod you can use the TestContext Object to get information about the current test run. ie: the DataRow. Take a look at the example below.

<TestClass()> Public Class DataTests

  Private testContextInstance As TestContext

  '''<summary>
  '''Gets or sets the test context which provides
  '''information about and functionality for the current test run.
  '''</summary>
  Public Property TestContext() As TestContext
   Get
      Return testContextInstance
   End Get
   Set(ByVal value As TestContext)
     testContextInstance = Value
   End Set
  End Property

  <TestMethod()> _
  'DataSource Attribute to get the Data from Northwind -> OrderDetailTestData
  <DataSource(
"Data Source=localhost;Initial Catalog=Northwind;Provider=SQLOLEDB;Integrated Security=SSPI;", "OrderDetailTestData")> _
  Public Sub OrderDataTest()
    Dim price As Decimal
    Dim expectedPrice As Decimal
    Dim MyDac As New MyWindowsApplication.MyDac

      MyDac.Load()
      'Use the TestContext Object to get the current DataRow for the current test run
      price = MyDac.getTotalPrice(
CInt(Me.TestContext.DataRow("OrderId")), CInt(Me.TestContext.DataRow("ProductId")))
      expectedPrice =
CDec(Me.TestContext.DataRow("Price"))

      Assert.AreEqual(price, expectedPrice)

  End Sub

End Class

Now just populate the OrderDetailTestData table with all the different data you want to pass through your method.