如何在 MSTest 中运行具有多个参数的测试方法?

NUnit 有一个名为 Value 的特性,如下所示:

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

这意味着测试方法将运行6次:

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

我们现在正在使用 MSTest,但是有没有相应的方法可以让我用多个参数运行相同的测试呢?

[TestMethod]
public void Mytest()
{
// ...
}
193269 次浏览

MSTest 不支持该特性,但是您可以实现自己的属性来实现该特性。

看看 使用 PostSharp 在 MSTest 中启用参数化测试

不幸的是,在 MSTest 的旧版本中不支持。显然有一个 可扩展性模型,您可以自己实现它。另一种选择是使用 数据驱动测试数据驱动测试

我个人的意见是坚持 NUnit 不过..。

从 VisualStudio2012更新1开始,MSTest 具有类似的特性。

与 NUnit 的 Value(或 TestCase)属性不完全相同,但是 MSTest 具有 DataSource属性,这允许您做类似的事情。

您可以将它连接到数据库或 XML 文件-它不像 NUnit 的特性那样简单,但它可以完成这项工作。

MSTest 有一个强大的属性 数据源。使用它,您可以按照要求执行数据驱动测试。您可以将测试数据放在 XML、 CSV 或数据库中。这里有一些链接可以指导你

编辑4 : 看起来这是在2016年6月17日 MSTest v2中完成的: < a href = “ https://blogs.msdn.microsoft.com/vision alstudioalm/2016/06/17/taking-the-MSTest-Framework-forward-with-MSTest-V2/”> https://blogs.msdn.microsoft.com/visualstudioalm/2016/06/17/taking-the-MSTest-framework-forward-with-MSTest-V2/

原答案 :

大约一周前,在 Visual Studio 2012 Update 1中,类似的事情现在已经成为可能:

[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 );
}

编辑 : 看起来这只能在 WinRT/Metro的单元测试项目中使用

EDIT 2 : 以下是在 Visual Studio 中使用“ Go To Definition”找到的元数据:

#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 : 这个问题是在 Visual Studio 的 UserVoice 论坛中提出的。 最新更新:

开始 · VisualStudio 团队管理 微软 Visual Studio 团队回应 · 2016年4月25日谢谢 我们已经开始工作了。

普拉塔普 · 拉克什曼视觉工作室

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

当然,还有另一种方法可以做到这一点,这个线程中还没有讨论过,即通过继承包含 TestMethod 的类的方法。在下面的示例中,只定义了一个 TestMethod,但是创建了两个测试用例。

在 VisualStudio2012中,它在 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) { }
    }
    

它的实现非常简单-您应该使用 TestContext属性和 TestPropertyAttribute

例子

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();
//...
}

编辑:

我准备了一些扩展方法来简化对 TestContext属性的访问,并且表现得像我们有几个测试用例一样。在这里可以看到处理简单测试属性的示例:

[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);
});
}

以及创建复杂测试对象的例子:

[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);
});
}

查看扩展 方法样本集以了解更多细节。

这个特性现在在 提前释放中,可以与 VisualStudio2015一起使用。

例如:

[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);
}
}

我无法让 DataRowAttribute在 Visual Studio 2015中工作,这就是我最终得到的结果:

[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;
}
}

这里真正的解决方案是只使用 NUnit (除非您像我在这个特殊实例中一样被困在 MSTest 中)。