[c#] How can we run a test method with multiple parameters in MSTest?

NUnit has a feature called Values, like below:

[Test]
public void MyTest(
    [Values(1,2,3)] int x,
    [Values("A","B")] string s)
{
    // ...
}

This means that the test method will run six times:

MyTest(1, "A")
MyTest(1, "B")
MyTest(2, "A")
MyTest(2, "B")
MyTest(3, "A")
MyTest(3, "B")

We're using MSTest now, but is there any equivalent for this so that I can run the same test with multiple parameters?

[TestMethod]
public void Mytest()
{
    // ...
}

This question is related to c# unit-testing nunit mstest vs-unit-testing-framework

The answer is


EDIT 4: Looks like this is completed in MSTest V2 June 17, 2016: https://blogs.msdn.microsoft.com/visualstudioalm/2016/06/17/taking-the-mstest-framework-forward-with-mstest-v2/

Original Answer:

As of about a week ago in Visual Studio 2012 Update 1 something similar is now possible:

[DataTestMethod]
[DataRow(12,3,4)]
[DataRow(12,2,6)]
[DataRow(12,4,3)]
public void DivideTest(int n, int d, int q)
{
  Assert.AreEqual( q, n / d );
}

EDIT: It appears this is only available within the unit testing project for WinRT/Metro. Bummer

EDIT 2: The following is the metadata found using "Go To Definition" within Visual Studio:

#region Assembly Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll, v11.0.0.0
// C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\MSTestFramework\11.0\References\CommonConfiguration\neutral\Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll
#endregion

using System;

namespace Microsoft.VisualStudio.TestPlatform.UnitTestFramework
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class DataTestMethodAttribute : TestMethodAttribute
    {
        public DataTestMethodAttribute();

        public override TestResult[] Execute(ITestMethod testMethod);
    }
}

EDIT 3: This issue was brought up in Visual Studio's UserVoice forums. Last Update states:

STARTED · Visual Studio Team ADMIN Visual Studio Team (Product Team, Microsoft Visual Studio) responded · April 25, 2016 Thank you for the feedback. We have started working on this.

Pratap Lakshman Visual Studio

https://visualstudio.uservoice.com/forums/330519-team-services/suggestions/3865310-allow-use-of-datatestmethod-datarow-in-all-unit


MSTest does not support that feature, but you can implement your own attribute to achieve that.

Have a look at Enabling parameterized tests in MSTest using PostSharp.


It's very simple to implement - you should use TestContext property and TestPropertyAttribute.

Example

public TestContext TestContext { get; set; }
private List<string> GetProperties()
{
    return TestContext.Properties
        .Cast<KeyValuePair<string, object>>()
        .Where(_ => _.Key.StartsWith("par"))
        .Select(_ => _.Value as string)
        .ToList();
}

//usage
[TestMethod]
[TestProperty("par1", "http://getbootstrap.com/components/")]
[TestProperty("par2", "http://www.wsj.com/europe")]
public void SomeTest()
{
    var pars = GetProperties();
    //...
}

EDIT:

I prepared few extension methods to simplify access to the TestContext property and act like we have several test cases. See example with processing simple test properties here:

[TestMethod]
[TestProperty("fileName1", @".\test_file1")]
[TestProperty("fileName2", @".\test_file2")]
[TestProperty("fileName3", @".\test_file3")]
public void TestMethod3()
{
    TestContext.GetMany<string>("fileName").ForEach(fileName =>
    {
        //Arrange
        var f = new FileInfo(fileName);

        //Act
        var isExists = f.Exists;

        //Asssert
        Assert.IsFalse(isExists);
    });
}

and example with creating complex test objects:

[TestMethod]
//Case 1
[TestProperty(nameof(FileDescriptor.FileVersionId), "673C9C2D-A29E-4ACC-90D4-67C52FBA84E4")]
//...
public void TestMethod2()
{
    //Arrange
    TestContext.For<FileDescriptor>().Fill(fi => fi.FileVersionId).Fill(fi => fi.Extension).Fill(fi => fi.Name).Fill(fi => fi.CreatedOn, new CultureInfo("en-US", false)).Fill(fi => fi.AccessPolicy)
        .ForEach(fileInfo =>
        {
            //Act
            var fileInfoString = fileInfo.ToString();

            //Assert
            Assert.AreEqual($"Id: {fileInfo.FileVersionId}; Ext: {fileInfo.Extension}; Name: {fileInfo.Name}; Created: {fileInfo.CreatedOn}; AccessPolicy: {fileInfo.AccessPolicy};", fileInfoString);
        });
}

Take a look to the extension methods and set of samples for more details.


MSTest has a powerful attribute called DataSource. Using this you can perform data-driven tests as you asked. You can have your test data in XML, CSV, or in a database. Here are few links that will guide you


I couldn't get The DataRowAttribute to work in Visual Studio 2015, and this is what I ended up with:

[TestClass]
public class Tests
{
    private Foo _toTest;

    [TestInitialize]
    public void Setup()
    {
        this._toTest = new Foo();
    }

    [TestMethod]
    public void ATest()
    {
        this.Perform_ATest(1, 1, 2);
        this.Setup();

        this.Perform_ATest(100, 200, 300);
        this.Setup();

        this.Perform_ATest(817001, 212, 817213);
        this.Setup();
    }

    private void Perform_ATest(int a, int b, int expected)
    {
        // Obviously this would be way more complex...

        Assert.IsTrue(this._toTest.Add(a,b) == expected);
    }
}

public class Foo
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

The real solution here is to just use NUnit (unless you're stuck in MSTest like I am in this particular instance).


This feature is in pre-release now and works with Visual Studio 2015.

For example:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    [DataRow(1, 2, 2)]
    [DataRow(2, 3, 5)]
    [DataRow(3, 5, 8)]
    public void AdditionTest(int a, int b, int result)
    {
        Assert.AreEqual(result, a + b);
    }
}

There is, of course, another way to do this which has not been discussed in this thread, i.e. by way of inheritance of the class containing the TestMethod. In the following example, only one TestMethod has been defined but two test cases have been made.

In Visual Studio 2012, it creates two tests in the TestExplorer:

  1. DemoTest_B10_A5.test
  2. DemoTest_A12_B4.test

    public class Demo
    {
        int a, b;
    
        public Demo(int _a, int _b)
        {
            this.a = _a;
            this.b = _b;
        }
    
        public int Sum()
        {
            return this.a + this.b;
        }
    }
    
    public abstract class DemoTestBase
    {
        Demo objUnderTest;
        int expectedSum;
    
        public DemoTestBase(int _a, int _b, int _expectedSum)
        {
            objUnderTest = new Demo(_a, _b);
            this.expectedSum = _expectedSum;
        }
    
        [TestMethod]
        public void test()
        {
            Assert.AreEqual(this.expectedSum, this.objUnderTest.Sum());
        }
    }
    
    [TestClass]
    public class DemoTest_A12_B4 : DemoTestBase
    {
        public DemoTest_A12_B4() : base(12, 4, 16) { }
    }
    
    public abstract class DemoTest_B10_Base : DemoTestBase
    {
        public DemoTest_B10_Base(int _a) : base(_a, 10, _a + 10) { }
    }
    
    [TestClass]
    public class DemoTest_B10_A5 : DemoTest_B10_Base
    {
        public DemoTest_B10_A5() : base(5) { }
    }
    

Not exactly the same as NUnit's Value (or TestCase) attributes, but MSTest has the DataSource attribute, which allows you to do a similar thing.

You can hook it up to database or XML file - it is not as straightforward as NUnit's feature, but it does the job.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to unit-testing

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0 How to test the type of a thrown exception in Jest Unit Tests not discovered in Visual Studio 2017 Class Not Found: Empty Test Suite in IntelliJ Angular 2 Unit Tests: Cannot find name 'describe' Enzyme - How to access and set <input> value? Mocking HttpClient in unit tests Example of Mockito's argumentCaptor How to write unit testing for Angular / TypeScript for private methods with Jasmine Why is the Visual Studio 2015/2017/2019 Test Runner not discovering my xUnit v2 tests

Examples related to nunit

How can I run NUnit tests in Visual Studio 2017? Selenium Error - The HTTP request to the remote WebDriver timed out after 60 seconds NUnit Unit tests not showing in Test Explorer with Test Adapter installed How can we run a test method with multiple parameters in MSTest? Verifying a specific parameter with Moq How do I use Assert.Throws to assert the type of the exception? How to find path of active app.config file? NUnit vs. MbUnit vs. MSTest vs. xUnit.net HRESULT: 0x80131040: The located assembly's manifest definition does not match the assembly reference

Examples related to mstest

Entity Framework Provider type could not be loaded? Unit testing private methods in C# How can we run a test method with multiple parameters in MSTest? How to write to Console.Out during execution of an MSTest test How can I write output from a unit test? Unit Testing: DateTime.Now How do I use Assert to verify that an exception has been thrown? NUnit vs. MbUnit vs. MSTest vs. xUnit.net

Examples related to vs-unit-testing-framework

How can we run a test method with multiple parameters in MSTest? How do I use Assert to verify that an exception has been thrown?