9

I know I can use data in files to drive unit test, for example data inside a csv or xml file.

For example:

[TestMethod]
[DataSource(
    "Microsoft.VisualStudio.TestTools.DataSource.CSV", 
    "Data.csv", 
    "Data#csv", 
    DataAccessMethod.Sequential)]
public void TestData() {}

I would like to know if there is a way that, instead of using a file, I can use a data structure that's already in memory to drive the tests.

Something like:

// this structure has the data to use in the unit test
var DataList = new List<string>();

[TestMethod]
[DataSource(
    "Microsoft.VisualStudio.TestTools.DataSource.IEnumerable",
    "DataList", 
    "DataList", 
    DataAccessMethod.Sequential)]
public void TestData() {}
Paulo Pinto
  • 427
  • 3
  • 10

6 Answers6

3

If it's in memory, my preference would be to not use DataSource, but use a T4 template to auto generate your unit tests instead. This way, you will only write the test once, but in the results for the test run, you will see an entry for each of the input you tested. Add this .tt file to your test project.

<#@ template debug="false" hostspecific="true" language="C#v3.5" #>
<#@ assembly name="System.Core.dll" #>
<#@ assembly name="System.Data.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>
<#
        List<string> DataList = AccessInMemoryData();
#>
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1
{
[TestClass]
public class UnitTest1
{
    <# foreach (string currentTestString in DataList) { #>
    [TestMethod]
    public void TestingString_<#= currentTestString #>
    {
    string currentTestString = "<#= currentTestString #>";
    // TODO: Put your standard test code here which will use the string you created above
    }
    <# } #>
}
}
Chaitanya
  • 5,203
  • 8
  • 36
  • 61
1

You can use MSTestHacks via NuGet to feed data from an IEnumerable, see this answer.

Community
  • 1
  • 1
Macke
  • 24,812
  • 7
  • 82
  • 118
1

A simple solution can be this...

private void TestData(IEnumerable what ) { ... your test method ... }

[TestMethod]
public void TestDataInMemory() { List<T> mylist = ...; this.TestData(mylist); }

[TestMethod]
[DataSource(
    "Microsoft.VisualStudio.TestTools.DataSource.CSV", 
    "Data.csv", 
    "Data#csv", 
    DataAccessMethod.Sequential)]
public void TestData() { this.TestData(testContextInstance ...) }

In this way you can use your test method both with data loaded from file and with data loaded from memory.

Salvatore Previti
  • 8,956
  • 31
  • 37
  • Thanks for your suggestion. Unfortunately, it seems to me that the TestDataInMemory() test will be run once only for any number of data entries, whereas the TestData() test will be run once per entry. For my purpose I would rather run one test per entry. – Paulo Pinto Nov 10 '11 at 00:51
1

I don't think you can do that with the [DataSource] attribute, but you can do a more or less the same thing manually.

Load your data in a method decorated with [AssemblyInitialize] or [ClassInitialize]. Then rewrite your tests to loop over the data. Unfortunately this way you will end up with a single test instead of separate results per test run.

Adam Lear
  • 38,111
  • 12
  • 81
  • 101
  • Yes, the data was already being set up in the [ClassInitialize] function, and I tried what you suggested. It does work, but a single test for all the data means the Asserts will stop the function on the first failed test. Not really what I was looking for. Thanks for the suggestion. – Paulo Pinto Nov 10 '11 at 17:38
1

I answered a similar question and the solution I have used before is to generate a simple CSV file from my in memory data.

Community
  • 1
  • 1
Magnus Lindhe
  • 7,157
  • 5
  • 48
  • 60
0

I think Gallio Ambience was supposed to solve this problem. I'm not sure what the state of the project is, currently.

mwilson
  • 1,255
  • 12
  • 17