How To: Create a Data-Driven Unit Test
Note
This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here
Using the Microsoft unit test framework for managed code, you can set up a unit test method to retrieve values used in the test method from a data source. The method is run successively for each row in the data source, which makes it easy to test a variety of input by using a single method.
This topic contains the following sections:
Running the test and viewing results
Creating a data-driven unit test involves the following steps:
Create a data source that contains the values that you use in the test method. The data source can be any type that is registered on the machine that runs the test.
Add a private TestContext field and a public
TestContext
property to the test class.Create a unit test method and add a DataSourceAttribute attribute to it.
Use the DataRow indexer property to retrieve the values that you use in a test.
The method under test
As an example, let's assume that we have created:
A solution called
MyBank
that accepts and processes transactions for different types of accounts.A project in
MyBank
calledBankDb
that manages the transactions for accounts.A class called
Maths
in theDbBank
project that performs the mathematical functions to ensure that any transaction is advantageous to the bank.A unit test project called
BankDbTests
to test the behavior of theBankDb
component.A unit test class called
MathsTests
to verify the behavior of theMaths
class.We will test a method in
Maths
that adds two integers using a loop:
public int AddIntegers(int first, int second)
{
int sum = first;
for( int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
Creating a data source
To test the AddIntegers
method, we create a data source that specifies a range of values for the parameters and the sum that you expect to be returned. In our example, we create a Sql Compact database named MathsData
and a table named AddIntegersData
that contains the following column names and values
FirstNumber | SecondNumber | Sum |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Adding a TestContext to the test class
The unit test framework creates a TestContext
object to store the data source information for a data-driven test. The framework then sets this object as the value of the TestContext
property that we create.
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
In your test method, you access the data through the DataRow
indexer property of the TestContext
.
Writing the test method
The test method for AddIntegers
is fairly simple. For each row in the data source, we call AddIntegers
with the FirstNumber and SecondNumber column values as parameters, and we verify the return value against Sum column value:
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
[TestMethod()]
public void AddIntegers_FromDataSourceTest()
{
var target = new Maths();
// Access the data
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.IntegerMethod(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Note that the Assert
method includes a message that displays the x
and y
values of a failed iteration. By default, the asserted values, expected
and actual
, are already included in the details of a failed test.
Specifying the DataSourceAttribute
The DataSource
attribute specifies the connection string for the data source and the name of the table that you use in the test method. The exact information in the connection string differs, depending on what kind of data source you are using. In this example, we used a SqlServerCe database.
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]
The DataSource attribute has three constructors.
[DataSource(dataSourceSettingName)]
A constructor with one parameter uses connection information that is stored in the app.config file for the solution. The dataSourceSettingsName is the name of the Xml element in the config file that specifies the connection information.
Using an app.config file allows you to change the location of the data source without making changes to the unit test itself. For information about how to create and use an app.config file, see Walkthrough: Using a Configuration File to Define a Data Source
[DataSource(connectionString, tableName)]
The DataSource
constructor with two parameters specifies the connection string for the data source and the name of the table that contains the data for the test method.
The connection strings depend on the type of the type of data source, but it should contain a Provider element that specifies the invariant name of the data provider.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Using TestContext.DataRow to access the data
To access the data in the AddIntegersData
table, use the TestContext.DataRow
indexer. DataRow
is a DataRow object, so we retrieve column values by index or column names. Because the values are returned as objects, we need to convert them to the appropriate type:
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
Running the test and viewing results
When you have finished writing a test method, build the test project. The test method appears in the Test Explorer window in the Not Run Tests group. As you run, write, and rerun your tests, Test Explorer displays the results in groups of Failed Tests, Passed Tests, and Not Run Tests. You can choose Run All to run all your tests, or choose Run... to choose a subset of tests to run.
The test results bar at the top of the Explorer is animated as your test runs. At the end of the test run, the bar will be green if all of the tests have passed or red if any of the tests have failed. A summary of the test run appears in the details pane at the bottom of the Test Explorer window. Select a test to view the details of that test in the bottom pane.
If you ran the AddIntegers_FromDataSourceTest
method in our example, the results bar turns red and the test method is moved to the Failed Tests A data-driven test fails if any of the iterated methods from the data source fails. When you choose a failed data-driven test in the Test Explorer window, the details pane displays the results of each iteration that is identified by the data row index. In our example, it appears that the AddIntegers
algorithm does not handle negative values correctly.
When the method under test is corrected and the test rerun, the results bar turns green and the test method is moved to the Passed Test group.
See Also
Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute Microsoft.VisualStudio.TestTools.UnitTesting.TestContext Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow Microsoft.VisualStudio.TestTools.UnitTesting.Assert How to: Create and Run a Unit Test Unit Test Your Code Run unit tests with Test Explorer Writing Unit Tests for the .NET Framework with the Microsoft Unit Test Framework for Managed Code