42

I know that MSTest doesn't support RowTest and similar tests.

What do MSTests users do? How is it possible to live without RowTest support?

I've seen DataDriven test features but sounds like too much overhead, is there any 3rd party patch or tool which allow me to do RowTest similar tests in MSTest?

AdrianHHH
  • 12,664
  • 16
  • 48
  • 79
dr. evil
  • 25,988
  • 28
  • 126
  • 198
  • 1
    Sadly, DaTest seems to only work with VS2008. –  May 27 '11 at 06:41
  • 1
    http://code.google.com/p/datest/wiki/DaTest – Todd Menier Apr 09 '10 at 17:19
  • Possible duplicate of [How to run a test method with multiple parameters in MSTest?](http://stackoverflow.com/questions/9021881/how-to-run-a-test-method-with-multiple-parameters-in-mstest) – Rob May 02 '16 at 23:44
  • Today you can use the [DataRow attribute](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.testtools.unittesting.datarowattribute?view=mstest-net-1.3.2) – Jacco Dieleman Apr 12 '19 at 08:11

6 Answers6

38
[TestMethod]
Test1Row1
{
    Test1(1,4,5);
}

[TestMethod]
Test1Row2
{
    Test1(1,7,8);
}

private Test1(int i, int j, int k)
{
   //all code and assertions in here
}
Tormod
  • 4,093
  • 1
  • 25
  • 45
  • 2
    This is the method I have used, and it also lets you give each "row" a separate, and hopefully descriptive name. – Mel Sep 14 '11 at 13:13
8

I know this is a late answer but hopefully it helps others out.

I looked everywhere for an elegant solution and ended up writing one myself. We use it in over 20 projects with thousands of unit tests and hundreds of thousands of iterations. Never once missed a beat.

https://github.com/Thwaitesy/MSTestHacks

1) Install the NuGet package.

2) Inherit your test class from TestBase

public class UnitTest1 : TestBase
{ }

3) Create a Property, Field or Method, that returns IEnumerable

public class UnitTest1 : TestBase
{
    private IEnumerable<int> Stuff
    {
        get
        {
            //This could do anything, get a dynamic list from anywhere....
            return new List<int> { 1, 2, 3 };
        }
    }
}

4) Add the MSTest DataSource attribute to your test method, pointing back to the IEnumerable name above. This needs to be fully qualified.

[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
    var number = this.TestContext.GetRuntimeDataSourceObject<int>();

    Assert.IsNotNull(number);
}

End Result: 3 iterations just like the normal DataSource :)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks;

namespace Namespace
{
    public class UnitTest1 : TestBase
    {
        private IEnumerable<int> Stuff
        {
            get
            {
                //This could do anything, get a dynamic list from anywhere....
                return new List<int> { 1, 2, 3 };
            }
        }

        [DataSource("Namespace.UnitTest1.Stuff")]
        public void TestMethod1()
        {
            var number = this.TestContext.GetRuntimeDataSourceObject<int>();

            Assert.IsNotNull(number);
        }
    }
}
Thwaitesy
  • 1,093
  • 2
  • 11
  • 14
6

We have added in support for DataRow in VS2012 Update1. See this blog for a breif introduction

In VS2012 Update1, this feature is currently limited to Windows store apps. In later versions, it is not this limited.

chwarr
  • 5,726
  • 1
  • 24
  • 52
allen
  • 4,589
  • 1
  • 20
  • 33
  • 8
    why is it limted to Windows store apps? Will it be available for regular test projects any time soon? – DevDave Mar 27 '13 at 13:08
  • 2
    xUnit has had this for so long. This is such a common scenario, why should this only be enabled for Windows Store Apps? It makes no sense. – CodeMonkeyKing Aug 15 '13 at 17:42
  • @DevDave while I do not know of the vnext plans there is an adapter available for legacy mstest projects that provides similar functionality. See this blog for details: http://blogs.msdn.com/b/vstsqualitytools/archive/2009/09/04/extending-the-visual-studio-unit-test-type-part-2.aspx – allen Aug 19 '13 at 05:24
  • @CodeMonkeyKing there were a variety of reasons the team could not get this functionality available for all test projects. All I can say is that, I agree, as a end user this is not very good. – allen Aug 19 '13 at 05:27
  • 2
    @allen understood. Working inside of the company that creates MSTest is more eye-opening than on the outside. Interesting that I would recommend using xUnit.net over MSTest. – CodeMonkeyKing Aug 20 '13 at 17:59
  • 2
    It is now available to all platforms, not only Windows Store applications. – Franklin Yu Dec 08 '17 at 19:13
  • I've edited the answer to the indicate that in later versions, the limitation has been relaxed. I don't know which version added support for which targets, so if anyone else does know, please help improve this answer. – chwarr Feb 01 '19 at 09:51
2

On my team that is locked into using the MS Test framework, we developed a technique that relies only on Anonymous Types to hold an array of test data, and LINQ to loop through and test each row. It requires no additional classes or frameworks, and tends to be fairly easy to read and understand. It's also much easier to implement than the data-driven tests using external files or a connected database.

For example, say you have an extension method like this:

public static class Extensions
{
    /// <summary>
    /// Get the Qtr with optional offset to add or subtract quarters
    /// </summary>
    public static int GetQuarterNumber(this DateTime parmDate, int offset = 0)
    {
        return (int)Math.Ceiling(parmDate.AddMonths(offset * 3).Month / 3m);
    }
}

You could use and array of Anonymous Types combined to LINQ to write a tests like this:

[TestMethod]
public void MonthReturnsProperQuarterWithOffset()
{
    // Arrange
    var values = new[] {
        new { inputDate = new DateTime(2013, 1, 1), offset = 1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 1, 1), offset = -1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 4, 1), offset = 1, expectedQuarter = 3},
        new { inputDate = new DateTime(2013, 4, 1), offset = -1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 7, 1), offset = 1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 7, 1), offset = -1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 10, 1), offset = 1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 10, 1), offset = -1, expectedQuarter = 3}
        // Could add as many rows as you want, or extract to a private method that
        // builds the array of data
    }; 
    values.ToList().ForEach(val => 
    { 
        // Act 
        int actualQuarter = val.inputDate.GetQuarterNumber(val.offset); 
        // Assert 
        Assert.AreEqual(val.expectedQuarter, actualQuarter, 
            "Failed for inputDate={0}, offset={1} and expectedQuarter={2}.", val.inputDate, val.offset, val.expectedQuarter); 
        }); 
    }
}

When using this technique it's helpful to use a formatted message that includes the input data in the Assert to help you identify which row causes the test to fail.

I've blogged about this solution with more background and detail at AgileCoder.net.

Gary.Ray
  • 5,973
  • 1
  • 25
  • 42
0

Similar to DaTest(not updated since 2008) solution using PostSharp is described in blog http://blog.drorhelper.com/2011/09/enabling-parameterized-tests-in-mstest.html

Michael Freidgeim
  • 21,559
  • 15
  • 127
  • 153
0

I have solved this issue by generating test class code with different number of generated test methods. You just have to download 2 files and include them into your project.
Then subclass a class with required number of rows in your test code and implement 2 abstract methods:

[TestClass]
public class Ha_ha_ha_Test: MsTestRows.Rows.TestRows_42<string>
{
    public override void TestMethod(string dataRow, int rowNumber)
    {
        Console.WriteLine(dataRow);
        Assert.IsFalse(dataRow.Contains("3"));
    }

    public override string GetNextDataRow(int rowNumber)
    {
        return "data" + rowNumber;
    }
}

More details:

https://github.com/dzhariy/mstest-rows

Dmytro Zharii
  • 280
  • 4
  • 14