Як ми можемо запустити метод тестування з кількома параметрами в MSTest?


140

NUnit має функцію під назвою Значення, як нижче:

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

Це означає, що метод тестування буде виконуватися шість разів:

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

Зараз ми використовуємо MSTest, але чи є для цього еквівалент, щоб я міг запустити один і той же тест з кількома параметрами?

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

Ви можете використовувати MSTestHacks, як описано в stackoverflow.com/a/19536942/52277 відповідь.
Майкл Фрейджім

Можливий дублікат Як RowTest з MSTest?
Майкл Фрейджім

@MichaelFreidgeim На це питання є кращі відповіді, ніж пропонована ціль
Rob

1
@Rob: IMHO, найбільш відповідна відповідь -MSTestHacks - Як RowTest з MSTest? відсутній у цьому питанні.
Майкл Фрейджім

@MichaelFreidgeim Можливо, хоча здається, що функціонал існує вже 3 1/2 роки ( stackoverflow.com/questions/9021881/… )
Роб

Відповіді:


46

На жаль, це не підтримується в старих версіях MSTest. Мабуть, є модель розширюваності, і ви можете її реалізувати самостійно . Іншим варіантом буде використання тестів, керованих даними .

Моя особиста думка була б просто дотримуватися NUnit, хоча ...

Щодо Visual Studio 2012, оновлення 1, MSTest має подібну функцію. Дивіться відповідь МакАдена .


Ми використовуємо Selenium, який генерує код NUnit, тому ми перейшли на використання NUnit замість цього :)
Світло

4
Я виявив, що щось подібне зараз можливо в Visual Studio 2012 Update 1, просто FYI для подальшого розгляду тих, хто дивиться на цю відповідь.
McAden

@McAden у вас є посилання з поясненням?
jeroenh

6
Я дав відповідь нижче із прикладом та посиланням на свою публікацію в блозі. У ньому згадуються необхідні атрибути, а також властивість "DisplayName" в атрибуті, що відрізняє випадки в Test Explorer. Про це також згадувалося в жовтневому оголошенні CTP (який зараз має офіційний реліз) blogs.msdn.com/b/visualstudioalm/archive/2012/10/26/… Я додав інформацію до цього питання, оскільки я витратив зовсім небагато часу на його пошуки. Сподіваємось, це врятує когось деякий час.
McAden

167

EDIT 4 : Схоже, це завершено в MSTest V2 17 червня 2016 року: 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 );
}

EDIT : Схоже, це доступно лише в рамках проекту тестування одиниць для WinRT / Metro . Бампер

EDIT 2 : Нижче наведені метадані, знайдені за допомогою "Перейти до визначення" у 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 : Ця проблема була розглянута на форумах UserVoice Visual Studio. Останнє оновлення:

НАЧАЛО · Команда Visual Studio ADMIN Команда Visual Studio (Команда продуктів, Microsoft Visual Studio) відповіла · 25 квітня 2016 р. Дякую за відгук. Ми почали працювати над цим.

Візуальна студія Пратапа Лакшмана

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


4
Зараз підтримується Windows Phone, а також оновлення 2 для Visual Studio 2012 (зараз, CTP 4)
Pedro Lamas

8
У мене є оновлення 1, але DataTestMethod і DataRow не розпізнаються, у якій бібліотеці ці атрибути?
DevDave

3
Чи є якесь офіційне джерело про DataTestMethod? У якому просторі імен він знаходиться, в якій збірці?
Ігор Ланкін

2
Я виявив, що UnitTestFramework.dll був встановлений на моєму комп’ютері, і після вручну посиланням на нього я зміг написати метод, використовуючи атрибут [DataTestMethod] з рядками даних, але я не можу отримати Test Explorer у Visual Studio 2012.3, щоб знайти метод.
Джош ДеЛонг

5
Я перейшов до файлового шляху "C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ v8.0 \ ExtensionSDKs \ MSTestFramework \ 11.0 \ References \ CommonConfiguration \ neutral \ Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll" на моєму комп'ютері і файл був там. Тому я посилався на це у своєму базовому проектному тестовому проекті. Відкриття dll у JustDecompile показує, що в бібліотеці є посилання лише на mscorlib, System та System.Core. Це не проект Windows Store.
Джош ДеЛонг

34

Ця функція знаходиться в попередньому випуску і працює з Visual Studio 2015.

Наприклад:

[TestClass]
public class UnitTest1
{
    [DataTestMethod]
    [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);
    }
}

Це правильна відповідь. Зверніть увагу , що не потрібно говорити [DataTestMethod] для використання [DataRow] ( stackoverflow.com/a/59162403/2540235 )
mattavatar

11

Не зовсім такий самий, як атрибути NUnit Value(або TestCase), але MSTest має DataSourceатрибут, який дозволяє зробити подібну дію.

Ви можете підключити його до бази даних або XML-файлу - це не так просто, як функція NUnit, але це робить цю роботу.


7

MSTest має потужний атрибут під назвою DataSource . Використовуючи це, ви можете виконувати керовані даними тести за вашим запитом. Ви можете мати свої тестові дані в XML, CSV або в базі даних. Ось декілька посилань, які вас направляють


6

Це дуже просто реалізувати - ви повинні використовувати 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);
        });
}

Погляньте на методи розширення та набір зразків для отримання більш детальної інформації.


2
Цей підхід працює, але не створює індивідуальних тестових випадків для кожного набору параметрів.
usr4896260

Ви можете використовувати щось складніше, як значення TestProperty (напр., "0-100"), розбирати та обробляти його в тілі тесту.
Андрій Бурикін

4

Звичайно, є ще один спосіб зробити це, про який не було сказано в цій темі, тобто шляхом успадкування класу, що містить TestMethod. У наступному прикладі визначено лише один тестовий метод, але зроблено два тестові випадки.

У Visual Studio 2012 він створює два тести в 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) { }
    }


3

Я не зміг домогтися 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, як я в цьому конкретному випадку).


3
слід розділити кожен тестовий виклик на окремий тест, щоб заощадити час, коли один із них перерветься. (що всі ми знаємо, що станеться)
срібло

Так, звісно. На практиці саме так було б зробити. У цьому випадку я просто ілюстрував це для простоти
Брендон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.