Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use data that's already in memory to drive unit tests?

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() {}
like image 840
Paulo Pinto Avatar asked Nov 10 '11 00:11

Paulo Pinto


3 Answers

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
    }
    <# } #>
}
}
like image 62
Chaitanya Avatar answered Oct 12 '22 12:10

Chaitanya


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.

like image 25
Salvatore Previti Avatar answered Oct 12 '22 12:10

Salvatore Previti


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.

like image 41
Adam Lear Avatar answered Oct 12 '22 12:10

Adam Lear