简体   繁体   English

MSTest 是否与 NUnit 的 TestCase 等效?

[英]Does MSTest have an equivalent to NUnit's TestCase?

I find the TestCase feature in NUnit quite useful as a quick way to specify test parameters without needing a separate method for each test.我发现 NUnit 中的TestCase特性非常有用,它可以快速指定测试参数,而无需为每个测试使用单独的方法。 Is there anything similar in MSTest? 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);  
     }  
 }  

Microsoft recently announced "MSTest V2" (see blog-article ). Microsoft 最近发布了“MSTest V2” (请参阅博客文章)。 This allows you to consistently (desktop, UWP, ...) use the DataRow -attribute!这使您可以始终如一地(桌面、UWP、...)使用DataRow

 [TestClass]  
 public class StringFormatUtilsTest  
 {  
     [DataTestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

Again, Visual Studio Express' Test Explorer unfortunately doesn't recognize these tests.同样,不幸的是,Visual Studio Express 的测试资源管理器无法识别这些测试。 But at least the "full" VS versions now support that feature!但至少“完整”VS 版本现在支持该功能!

To use it, just install the NuGet packages MSTest.TestFramework and MSTest.TestAdapter (both pre-release as of now).要使用它,只需安装 NuGet 包MSTest.TestFrameworkMSTest.TestAdapter (目前都是预发布版)。

Older answer:较旧的答案:

If don't have to stick with MSTest and you're just using it for being able to run the tests via Test Explorer如果不必坚持使用 MSTest 并且您只是为了能够通过测试资源管理器运行测试而使用它because you only have a Visual Studio Express edition因为您只有 Visual Studio Express 版本, then this might be a solution for you: ,那么这可能是您的解决方案:

There's the VsTestAdapter VSIX extension for being able to run NUnit tests via Test Explorer. VsTestAdapter VSIX 扩展可以通过测试资源管理器运行 NUnit 测试。 Unfortunately, VS Express users can't install extensions... But fortunately the VsTestAdapter comes with a plain NuGet-Package , too!不幸的是,VS Express 用户无法安装扩展……但幸运的是VsTestAdapter 也带有一个普通的 NuGet-Package

So, if you're a VS Express user, just install the VsTestAdapter NuGet-Package and enjoy running your NUnit tests/testcases via Test Explorer!因此,如果您是 VS Express 用户,只需安装 VsTestAdapter NuGet-Package 并享受通过测试资源管理器运行您的 NUnit 测试/测试用例的乐趣!


Unfortunately the aforementioned statement isn't true.不幸的是,上述说法是不正确的。 While it's perfectly possible to install the package via an Express edition, it's useless, since it can't utilize the Test Explorer.虽然通过 Express 版本安装软件包是完全可能的,但它没有用,因为它不能使用测试资源管理器。 There's previously been a side note on an older version of the TestAdapter, which was removed from the 2.0.0's description page :以前有一个关于旧版本的 TestAdapter 的旁注,它已从2.0.0 的描述页面中删除:

Note that it doesn't work with VS Express请注意,它不适用于 VS Express

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.我们在 20 多个项目中使用它,其中包含数千个单元测试和数十万次迭代。 Never once missed a beat.从来没有错过任何一个节拍。

https://github.com/Thwaitesy/MSTestHacks https://github.com/Thwaitesy/MSTestHacks

1) Install the NuGet package. 1)安装NuGet包。

2) Inherit your test class from TestBase 2)从 TestBase 继承你的测试类

public class UnitTest1 : TestBase
{ }

3) Create a Property, Field or Method, that returns IEnumerable 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) Add the MSTest DataSource attribute to your test method, pointing back to the IEnumerable name above. 4)将 MSTest DataSource 属性添加到您的测试方法,指向上面的 IEnumerable 名称。 This needs to be fully qualified.这需要完全合格。

[TestMethod]
[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 :)最终结果: 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);
        }
    }
}

I know this is another late answer, but 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.我知道这是另一个迟到的答案,但在我的团队被锁定在使用 MS 测试框架中,我们开发了一种技术,该技术仅依赖于匿名类型来保存一组测试数据,并使用 LINQ 来循环并测试每一行。 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:您可以将匿名类型数组与 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); 
        }); 
    }
}

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.使用此技术时,使用包含 Assert 中输入数据的格式化消息来帮助您识别导致测试失败的行是很有帮助的。

I've blogged about this solution with more background and detail at AgileCoder.net .我在AgileCoder.net 上发表了有关此解决方案的更多背景和详细信息的博客

Khlr gave a good detailed explanations and apparently this approach started working in VS2015 Express for Desktop. Khlr 给出了很好的详细解释,显然这种方法开始在 VS2015 Express for Desktop 中起作用。 I tried to leave the comment, but my lack of reputation didn't allow me to do so.我试图发表评论,但我缺乏声誉不允许我这样做。

Let me copy the solution here:让我在这里复制解决方案:

[TestClass]  
 public class StringFormatUtilsTest  
 {  
     [TestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&amp;amp;5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

To use it, just install the NuGet packages MSTest.TestFramework and MSTest.TestAdapter .要使用它,只需安装 NuGet 包MSTest.TestFrameworkMSTest.TestAdapter

One problem is一个问题是

Error CS0433 The type 'TestClassAttribute' exists in both 'Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0 and 'Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0错误 CS0433 类型“TestClassAttribute”存在于“Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0 和”Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0

So, please remove Microsoft.VisualStudio.QualityTools.UnitTestFramework from references of the project.因此,请从项目的引用中删除Microsoft.VisualStudio.QualityTools.UnitTestFramework

You're very welcome to edit the original reply and delete this one.非常欢迎您编辑原始回复并删除此回复。

Consider using DynamicDataAttribute :考虑使用DynamicDataAttribute

NUnit Test cases 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 Test cases 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);
}

MSTest has the DataSource attribute, which will allow you to feed it a database table, csv, xml, etc. I've used it and it works well. MSTest 具有 DataSource 属性,这将允许您向它提供一个数据库表、csv、xml 等。我已经使用过它并且运行良好。 I don't know of a way to put the data right above as attributes as in your question, but it's very easy to set up the external data sources and files can be included in the project.我不知道有什么方法可以像您的问题一样将数据作为属性放在正上方,但是设置外部数据源非常容易,并且可以将文件包含在项目中。 I had it running an hour from when I started, and I'm not an automated test expert.我从一开始就让它运行了一个小时,而且我不是自动化测试专家。

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 has a full tutorial based on database input. 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/ has a tutorial based on XML file input. http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/有一个基于 XML 文件输入的教程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM