Data-Driven Unit Testing using Excel in Visual Studio

Data-Driven Unit Tests are very powerful but, it seems to me, rarely used feature in Visual Studio. Although they are not suitable in all situations they can be of a great help. Personally, I used them to drive testing of business rules. In one of the scenarios I had 9 parameters and they had about 900 possible combinations. I was able to cut the number of possible tests and I did so, but the point is that in some scenarios just typing in test data into source code is very laborious and error prone and can be easily avoided.

Intro

There are basically 3 ways to data-drive your unit tests in Visual Studio:

I prefer Excel files to drive my tests. All the tools are there to create your data, it is the fastest to setup and you don’t need external dependencies. For database you need to use database server, then question is if all developers have the access, or if every developer should have server locally installed, again what happens if you want to work from home? If you want to use XML it is insane to type it in a text editor, you need tools. CSV seems simplest but I had issues with formatting and it was real pain to maintain.

The problem with Excel might be that you don’t have it :) You can use Google Documents or Open Office for free with the same effect.

Step by Step

Unfortunately New Test Data Source Wizard won’t help you much when it comes to excel files, so we’ll have to do it manually. I prepared some simple test solution (Visual Studio 2008) with sample excel file to use for testing. First of all create your unit tests project as you would normally do. Then add some test data file:

I added here testData.xls with properties Build Action: Content and Copy to Output Directory: Copy if newer should be set. We need action to be content so the file is copied to the output directory, and so we can later pick it up for our testing purposes by using DeploymentItemAttribute. Now we have to embelish our test method with some new attributes:

TestMethod attribute is there since this is a test method. DeploymentItem attribute is there since we want to deploy our testData.xls with our test. This attribute affects our DataSource attribute. I wanted to keep it simple, if the file is not deployed with the test then absolute path to the file is required and then there might be issues with developers having source in different folders.

DataSource attribute is interesting:

[DataSource(
“System.Data.Odbc”,
@”Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=testData.xls;DefaultDir=.”,
“Sheet1$”,
DataAccessMethod.Sequential)]

We are using Odbc provider, the name of the provider is the first parameter of the attribute. The next one is the connection string. Dbq parameter in the connection string is the file name of the excel file. Since the file will be deployed to the same folder where the test is going to be ran we can just use the file name (otherwise absolute path to the file would be required), and for the same reason we can use DefaultDir=.

The third parameters is the table name and since I haven’t changed the name of the worksheet it should be Sheet1$. At the end is data access method and it can be random or sequential.

This is how the content of the excel file might look like:

The first row are the column names later used in the test:

So this is a very simple test. The data is normally used as:

int a = (int)((double)TestContext.DataRow[”a”]);

TestContext.DataRow has all the data from the current row. One note is due: when you get number from excel it is always double, so in this case it has to be casted from object to double and then to int. Another note is due for Visual Studio 2005, to be able to access TestContext add the following code:

private TestContext testContext;
public TestContext TestContext
{
get { return testContext; }
set { testContext = value; }
}

It magically works, Visual Studio 2008 adds this code automatically for you.

I deliberately introduced a bug so this test won’t be successful so I can just show you couple of more things:

You get a nice report with all the results laid out in a table and you have an index of the data which had been used in the test in Data Row column. One tip: create Data Row column or name it whatever you want in your excel file so you can easily navigate to the data row that caused the test to fail:

It is by no means required but it is handy when you have 50 or more records in your excel file. You can use simple formula as shown on the picture to populate the column. Mind though that Visual Studio will use all the rows from the excel file as long as there is at least one populated column in the row.

Closing words

Having the separate data file to be used in your tests helps obviously separate your data and the test code, but especially keeps your test data clean and easily maintainable. Using excel for the test data files is just natural and familiar. Use it wherever it makes sense.

8 Responses to “Data-Driven Unit Testing using Excel in Visual Studio”


  1. 1 Michal Bali

    Very interesting. Thank you. I’ll just add few links that might be useful - testing using word documents or a wiki:
    http://fit.c2.com/
    http://fitnesse.org/
    http://fit-for-rules.sourceforge.net/
    Regards,
    Michal

  2. 2 Mihailo Lalevic

    Hi Michal,
    Thanks for the links! I’m definitely going to investigate what they have to offer. My first impression is that they are more collaboration and customer oriented, which makes them very suitable for business rules testing and documentation. Acceptance tests would be perfect candidates for this tools.
    However I don’t see them as something that would drive my unit tests. I would not like to be relying on external resources for unit tests as well I don’t need that degree of collaboration sophistication. For tests that would be interested to customer - I would definitely use them.
    Cheers,
    Mihailo

  3. 3 Iva

    Hi,

    I’m actually using excel as my data source for my unit testing. Everything was working great, until I ran the tests on a machine that did not have MS Excel installed. The error I received was: “The unit test adapter failed to connect to the data source or to read the data.”

    What do you suggest I do in this case? Installing MS Office on every machine is not an option (this is because machines are wiped out and new ones are created each time). Any suggestions would be great!

    Thanks in advance.

  4. 4 Mihailo Lalevic

    Hi Iva,
    You don’t need to install MS Excel, I think Office System Drivers would work:

    http://www.microsoft.com/downloads/details.aspx?familyid=7554F536-8C28-4598-9B72-EF94E038C891&displaylang=en

    I was just reading this post to setup my tests with excel, and most of the time the error was about wrong path to the file, or the wrong worksheet name. Once I forgot to set Copy To Output Folder: Copy if newer in the excel file property. And once I omitted DeploymentItem attribute. It can be any of those, it always gives the same error: The unit test adapter failed to connect to the data source or to read the data.

    Hope this helps. Sorry about late reply, I thought I was getting email notifications on comments here :(

    Cheers,
    Mihailo

  5. 5 Rahul

    Hi,

    It is very good and very much interesting…

    but I want to know than can we create new column in exel as actual result and add the result of text case into it for every input.

  6. 6 Benj

    How did you come up with the connectionstring for Excel? I copied and pasted your connectionstring and substituted mine. When I ran my Unit test project, I got an error from the Test Results window saying “the unit test adapter failed to connect to the data source or to read the data”…

  7. 7 Mihailo Lalevic

    @Rahul

    Do you want to store result back into your excel file? You can’t do it with TestContext. I don’t think you can do it even with some hacking since I’d presume Visual Studio will keep the file locked.

  8. 8 Mihailo Lalevic

    @Benj

    Have you added DeploymentItem attribute as in the third image from the top? If you don’t specify it like that you’ll need your file in a well known location and you’ll have to change the path to point to it.

Leave a Reply