MSTest'te birden çok parametreli bir test yöntemini nasıl çalıştırabiliriz?


140

NUnit aşağıdaki gibi Değerler adlı bir özelliğe sahiptir:

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

Bu, test yönteminin altı kez çalışacağı anlamına gelir:

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

Şimdi MSTest kullanıyoruz, ancak aynı testi birden fazla parametre ile çalıştırabilmem için buna eşdeğer bir şey var mı?

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

Stackoverflow.com/a/19536942/52277 yanıtında açıklandığı gibi MSTestHacks kullanabilirsiniz .
Michael Freidgeim


@MichaelFreidgeim Bu soru, önerilen hedefinizden daha iyi cevaplara sahip
Rob

1
@Rob: IMHO, en uygun cevap -MSTestHacks - MSTest ile RowTest nasıl? bu soruda eksik.
Michael Freidgeim

@MichaelFreidgeim Belki de, işlevsellik 3 1/2 yıldır varlığını sürdürüyor olsa da ( stackoverflow.com/questions/9021881/… )
Rob

Yanıtlar:


46

Maalesef MSTest'in eski sürümlerinde desteklenmemektedir. Görünüşe göre bir genişletilebilirlik modeli var ve bunu kendiniz uygulayabilirsiniz . Başka bir seçenek de veriye dayalı testleri kullanmak olacaktır .

Benim kişisel fikrim sadece NUnit ile sopa olurdu ...

Visual Studio 2012, güncelleştirme 1'den itibaren MSTest de benzer bir özelliğe sahiptir. McAden'ın cevabına bakın .


NUnit kodu üreten Selenium kullanıyoruz, bunun yerine NUnit kullanmaya başladık :)
The Light

4
Visual Studio 2012 Güncelleştirme 1'de benzer bir şeyin mümkün olduğunu buldum, bu cevaba bakan herkesin gelecekteki değerlendirmesi için sadece FYI.
McAden

@McAden açıklamalı bir bağlantınız var mı?
jeroenh

6
Aşağıda bir örnek ve blog yazımın bağlantısını içeren bir cevap verdim. Gerekli özniteliklerden ve ayrıca özniteliğin Test Gezgini'ndeki durumları ayıran "DisplayName" özelliğinden bahseder. Ayrıca CTP'nin (şimdi resmi sürümü olan) Ekim duyurusunda da bahsedildi blogs.msdn.com/b/visualstudioalm/archive/2012/10/26/… Bu SO sorusuna bilgi ekledim çünkü onu aramak için biraz zaman harcadı. Umarım bu biraz zaman kazanır.
McAden

167

DÜZENLEME 4 : Bunun MSTest V2'de tamamlandığı anlaşılıyor 17 Haziran 2016: https://blogs.msdn.microsoft.com/visualstudioalm/2016/06/17/taking-the-mstest-framework-forward-with-mstest- v2 /

Orijinal Yanıt :

Yaklaşık bir hafta önce Visual Studio 2012 Güncelleştirme 1'de benzer bir şey artık mümkün:

[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 : Bu sadece WinRT / Metro için birim test projesinde kullanılabilir gibi görünüyor . serseri

DÜZENLEME 2 : Aşağıdakiler, Visual Studio'da "Tanıma Git" kullanılarak bulunan meta verilerdir:

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

DÜZENLEME 3 : Bu sorun Visual Studio'nun UserVoice forumlarında gündeme getirildi. Son Güncelleme durumu:

BAŞLADI · Visual Studio Ekibi ADMIN Visual Studio Ekibi (Ürün Ekibi, Microsoft Visual Studio) yanıt verdi · 25 Nisan 2016 Geri bildiriminiz için teşekkür ederiz. Bunun üzerinde çalışmaya başladık.

Pratap Lakshman Görsel Stüdyosu

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


4
Windows Phone da artık desteklenmektedir, Visual Studio 2012 Güncelleştirme 2 (şu anda CTP 4)
Pedro Lamas

8
Güncelleştirme 1 var ama DataTestMethod ve DataRow tanınmıyor, bu öznitelikler hangi kitaplıkta?
DevDave

3
DataTestMethod hakkında resmi bir kaynak var mı? Hangi montaj alanında, hangi montajda?
Igor Lankin

2
UnitTestFramework.dll bilgisayarımda yüklü bulundu ve el ile başvurduktan sonra veri satırları ile [DataTestMethod] özniteliğini kullanarak bir yöntem yazmak mümkün ama yöntemi bulmak için Visual Studio 2012.3 Test Gezgini alamıyorum.
Josh DeLong

5
Bilgisayarımdaki "C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ v8.0 \ ExtensionSDKs \ MSTestFramework \ 11.0 \ References \ CommonConfiguration \ neutral \ Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll" dosya yoluna gittim ve dosya oradaydı. Bu yüzden temel birim test projemde bunu referans aldım. DLL dosyasını JustDecompile içinde açmak kütüphanenin sadece mscorlib, System ve System.Core referanslarına sahip olduğunu gösterir. Bu bir Windows Mağazası projesi değil.
Josh DeLong

34

Bu özellik ön sürümde şimdi ve Visual Studio 2015 ile çalışıyor.

Örneğin:

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

Bu doğru cevap. [DataRow] 'u kullanmak için [DataTestMethod] demenin gerekli olmadığını unutmayın ( stackoverflow.com/a/59162403/2540235 )
mattavatar

11

NUnit'in Value(veya TestCase) nitelikleriyle tam olarak aynı değildir , ancak MSTest DataSourcebenzer bir şey yapmanıza izin veren özelliğe sahiptir .

Veritabanına veya XML dosyasına bağlayabilirsiniz - NUnit'in özelliği kadar basit değildir, ancak işi yapar.



6

Uygulamak çok basit - TestContextmülkiyet ve kullanmalısınız TestPropertyAttribute.

Misal

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

DÜZENLE:

TestContextMülke erişimi basitleştirmek ve birkaç test vakamız olduğu gibi davranmak için birkaç uzatma yöntemi hazırladım . Basit test özelliklerini işleyen örneğe bakın:

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

ve karmaşık test nesneleri oluşturma örneği:

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

Daha fazla ayrıntı için genişletme yöntemlerine ve örnek setine göz atın .


2
Bu yaklaşım işe yarar, ancak her parametre seti için ayrı test senaryoları oluşturmaz.
29.08.2060

TestProperty değeri (ör. "0-100") olarak daha karmaşık bir şey kullanabilir, ayrıştırıp test gövdesinde işleyebilirsiniz.
Andrey Burykin

4

Elbette, bu iş parçacığında tartışılmayan başka bir yol daha vardır, yani TestMethod'u içeren sınıfın kalıtımı yoluyla. Aşağıdaki örnekte, yalnızca bir TestMethod tanımlanmıştır, ancak iki test örneği yapılmıştır.

Visual Studio 2012'de, TestExplorer'da iki sınama oluşturur:

  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

DataRowAttributeVisual Studio 2015'te çalışmak için alamadım ve sonuçta ben:

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

Buradaki gerçek çözüm NUnit'i kullanmaktır (bu örnekte olduğu gibi MSTest'te takılı kalmazsanız).


3
bunlardan birinin kırılacağı zamandan tasarruf etmek için her bir test çağrısını ayrı bir teste bölmelisiniz. (ki hepimiz bileceğiz)
gümüş

Evet tabi ki. Pratikte böyle yapılırdı. Bu durumda sadece basitlik için gösteriyordum
Brandon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.