我发现NUnit中的TestCase
功能非常有用,可以快速指定测试参数,而无需为每个测试使用单独的方法。 MSTest有什么类似的东西吗?
[TestFixture]
public class StringFormatUtilsTest
{
[TestCase("tttt", "")]
[TestCase("", "")]
[TestCase("t3a4b5", "345")]
[TestCase("3&5*", "35")]
[TestCase("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
答案 0 :(得分:41)
如果不必坚持使用MSTest并且您只是使用它来通过Test Explorer 运行测试,因为您只有Visual Studio Express版,那么这可能是为您解决方案:
有VsTestAdapter VSIX extension能够通过Test Explorer运行NUnit测试。不幸的是,VS Express用户无法安装扩展程序...... 但幸运的是VsTestAdapter comes with a plain NuGet-Package也是如此!
因此,如果您是VS Express用户,只需安装VsTestAdapter NuGet-Package并享受通过测试资源管理器运行NUnit测试/测试用例!
不幸的是,上述陈述并非如此。虽然完全可以通过Express版本安装软件包,但它没用,因为它无法使用Test Explorer。之前有关于older version TestAdapter的旁注,该帖已从2.0.0's description page中删除:
请注意,它不适用于VS Express
<强>更新强>
微软最近宣布“MSTest V2”(见blog-article)。这使您可以始终如一地(桌面,UWP,...)使用DataRow
- 属性!
[TestClass]
public class StringFormatUtilsTest
{
[DataTestMethod]
[DataRow("tttt", "")]
[DataRow("", "")]
[DataRow("t3a4b5", "345")]
[DataRow("3&amp;5*", "35")]
[DataRow("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
再一次,Visual Studio Express的测试资源管理器遗憾地无法识别这些测试。但至少“完整”VS版本现在支持该功能!
要使用它,只需安装NuGet软件包MSTest.TestFramework和MSTest.TestAdapter(截至目前均已预发布)。
答案 1 :(得分:34)
我知道这是一个迟到的答案,但希望它可以帮助其他人。
我到处寻找一个优雅的解决方案,最后自己写了一个。我们在20多个项目中使用它,进行了数千次单元测试和数十万次迭代。从来没有错过任何一个节拍。
https://github.com/Thwaitesy/MSTestHacks
1)安装NuGet包。
2)从TestBase
继承您的测试类public class UnitTest1 : TestBase
{ }
3)创建一个返回IEnumerable的属性,字段或方法
[TestClass]
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)将MSTest DataSource属性添加到测试方法,指向上面的IEnumerable名称。这需要完全合格。
[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Assert.IsNotNull(number);
}
结束结果: 3次迭代就像普通的DataSource一样:)
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks;
namespace Namespace
{
[TestClass]
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 };
}
}
[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Assert.IsNotNull(number);
}
}
}
答案 2 :(得分:13)
我知道这是另一个迟到的答案,但在我的团队被锁定使用MS Test框架时,我们开发了一种技术,它只依赖于匿名类型来保存测试数据数组,并且LINQ循环并测试每一行。它不需要额外的类或框架,并且往往相当容易阅读和理解。它比使用外部文件或连接数据库的数据驱动测试更容易实现。
例如,假设您有这样的扩展方法:
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);
}
}
你可以使用和匿名类型的数组组合到LINQ来编写这样的测试:
[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);
});
}
}
使用此技术时,使用包含Assert中输入数据的格式化消息有助于您确定哪一行导致测试失败。
我在AgileCoder.net了解了有关此解决方案的更多背景和详细信息。
答案 3 :(得分:6)
Khlr给出了详细的解释,显然这种方法开始在VS2015 Express for Desktop中使用。 我试图留下评论,但我缺乏声誉不允许我这样做。
让我在这里复制解决方案:
[TestClass]
public class StringFormatUtilsTest
{
[TestMethod]
[DataRow("tttt", "")]
[DataRow("", "")]
[DataRow("t3a4b5", "345")]
[DataRow("3&amp;5*", "35")]
[DataRow("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
要使用它,只需安装NuGet包MSTest.TestFramework和MSTest.TestAdapter。
一个问题是
错误CS0433两者中都存在“TestClassAttribute”类型 “Microsoft.VisualStudio.QualityTools.UnitTestFramework, 版本= 10.0.0.0和 'Microsoft.VisualStudio.TestPlatform.TestFramework,Version = 14.0.0.0
因此,请从项目参考中删除 Microsoft.VisualStudio.QualityTools.UnitTestFramework 。
非常欢迎您编辑原始回复并删除此回复。
答案 4 :(得分:0)
MSTest具有DataSource属性,允许您为其提供数据库表,csv,xml等。我已经使用过它并且效果很好。我不知道如何将数据放在上面作为问题的属性,但是设置外部数据源非常容易,文件可以包含在项目中。我从一开始就运行了一个小时,而且我不是自动化测试专家。
https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396有一个基于数据库输入的完整教程。
http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/有一个基于XML文件输入的教程。
答案 5 :(得分:0)
考虑使用 DynamicDataAttribute:
NUnit 测试用例
private static readonly IEnumerable<TestCaseData> _testCases = new[]
{
new TestCaseData("input value 1").Returns(new NameValueCollection { { "a", "b" } }),
new TestCaseData("input value 2").Returns(new NameValueCollection { { "a", "b" } }),
/* .. */
};
[TestCaseSource(nameof(_testCases))]
public NameValueCollection test_test(string str)
{
var collection = new NameValueCollection();
collection.TestedMethod(str);
return collection;
}
MSTest 测试用例
private static IEnumerable<object[]> _testCases
{
get
{
return new[]
{
new object[] { "input value 1", new NameValueCollection { { "a", "b" } } },
new object[] { "input value 2", new NameValueCollection { { "a", "b" } } },
/* .. */
};
}
}
[TestMethod]
[DynamicData(nameof(_testCases))]
public void test_test(string str, NameValueCollection expectedResult)
{
var collection = new NameValueCollection();
collection.TestedMethod(str);
CollectionAssert.AreEqual(expectedResult, collection);
}