Wie führe ich eine Testmethode mit mehreren Parametern in MSTest aus?

140

NUnit hat eine Funktion namens Werte, wie unten:

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

Dies bedeutet, dass die Testmethode sechsmal ausgeführt wird:

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

Wir verwenden jetzt MSTest. Gibt es dafür ein Äquivalent, damit ich denselben Test mit mehreren Parametern ausführen kann?

[TestMethod]
public void Mytest()
{
    // ...
}
Das Licht
quelle
Sie können MSTestHacks verwenden, wie unter stackoverflow.com/a/19536942/52277 Antwort beschrieben.
Michael Freidgeim
Mögliches Duplikat von RowTest mit MSTest?
Michael Freidgeim
@ MichaelFreidgeim Diese Frage hat bessere Antworten als Ihr vorgeschlagenes Ziel
Rob
1
@Rob: IMHO, die am besten geeignete Antwort -MSTestHacks - Wie rudere ich mit MSTest? fehlt in dieser Frage.
Michael Freidgeim
@ MichaelFreidgeim Vielleicht, obwohl es scheint, dass die Funktionalität seit 3 ​​1/2 Jahren existiert ( stackoverflow.com/questions/9021881/… )
Rob

Antworten:

46

Es wird in MSTest leider nicht unterstützt. Anscheinend gibt es ein Erweiterungsmodell, das Sie selbst implementieren können . Eine andere Möglichkeit wäre die Verwendung datengesteuerter Tests .

Meine persönliche Meinung wäre jedoch, einfach bei NUnit zu bleiben ...

BEARBEITEN: Ab Visual Studio 2012, Update 1, verfügt MSTest über eine ähnliche Funktion. Siehe @ McAdens Antwort unten.

jeroenh
quelle
Wir verwenden Selenium, das NUnit-Code generiert, also haben wir stattdessen NUnit verwendet :)
The Light
4
Ich habe festgestellt, dass etwas Ähnliches jetzt in Visual Studio 2012 Update 1 möglich ist, nur zu Ihrer Information, um künftig alle zu berücksichtigen, die sich diese Antwort ansehen.
McAden
@ McAden hast du einen Link mit einer Erklärung?
Jeroenh
6
Ich gab unten eine Antwort mit einem Beispiel und einem Link zu meinem Blog-Beitrag. Es werden die erforderlichen Attribute sowie die Eigenschaft "DisplayName" für das Attribut erwähnt, das die Fälle im Test-Explorer unterscheidet. Es wurde auch in der Oktober-Ankündigung des CTP (das jetzt die offizielle Veröffentlichung hat) blogs.msdn.com/b/visualstudioalm/archive/2012/10/26/… erwähnt. Ich habe die Informationen zu dieser SO-Frage hinzugefügt, weil ich verbrachte ziemlich viel Zeit damit, danach zu suchen. Hoffentlich spart dies jemandem etwas Zeit.
McAden
167

BEARBEITEN 4 : Dies scheint in MSTest V2 am 17. Juni 2016 abgeschlossen zu sein: https://blogs.msdn.microsoft.com/visualstudioalm/2016/06/17/taking-the-mstest-framework-forward-with-mstest- v2 /

Ursprüngliche Antwort :

Seit ungefähr einer Woche ist in Visual Studio 2012 Update 1 etwas Ähnliches möglich:

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

BEARBEITEN : Dies scheint nur im Unit-Test-Projekt für WinRT / Metro verfügbar zu sein . Schade

BEARBEITEN 2 : Die folgenden Metadaten werden mit "Gehe zu Definition" in Visual Studio gefunden:

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

BEARBEITEN 3 : Dieses Problem wurde in den UserVoice-Foren von Visual Studio angesprochen. Letzte Aktualisierung besagt:

STARTED · Visual Studio-Team ADMIN Visual Studio-Team (Produktteam, Microsoft Visual Studio) hat geantwortet · 25. April 2016 Vielen Dank für das Feedback. Wir haben begonnen, daran zu arbeiten.

Pratap Lakshman Visual Studio

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

McAden
quelle
4
Windows Phone wird jetzt auch mit Visual Studio 2012 Update 2 (derzeit CTP 4) unterstützt
Pedro Lamas
8
Ich habe Update 1, aber DataTestMethod und DataRow werden nicht erkannt. In welcher Bibliothek befinden sich diese Attribute?
DevDave
3
Gibt es eine offizielle Quelle zu DataTestMethod? In welchem ​​Namespace befindet es sich, in welcher Assembly?
Igor Lankin
2
Ich habe festgestellt, dass die UnitTestFramework.dll auf meinem Computer installiert war, und nachdem ich sie manuell referenziert habe, konnte ich eine Methode mit dem Attribut [DataTestMethod] mit Datenzeilen schreiben, aber der Test Explorer in Visual Studio 2012.3 kann die Methode nicht finden.
Josh DeLong
5
Ich ging auf meinem Computer zum Dateipfad "C: \ Programme (x86) \ Microsoft SDKs \ Windows \ v8.0 \ ExtensionSDKs \ MSTestFramework \ 11.0 \ References \ CommonConfiguration \ neutral \ Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll" und die Datei war da. Also habe ich in meinem grundlegenden Unit-Test-Projekt darauf verwiesen. Das Öffnen der DLL in JustDecompile zeigt, dass die Bibliothek nur Verweise auf mscorlib, System und System.Core enthält. Es ist kein Windows Store-Projekt.
Josh DeLong
34

Diese Funktion ist jetzt in der Vorabversion und funktioniert mit VS 2015.

Beispielsweise:

[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);
    }
}
Pompair
quelle
Dies ist die richtige Antwort. Beachten Sie, dass es nicht erforderlich ist, [DataTestMethod] zu sagen, um [DataRow] ( stackoverflow.com/a/59162403/2540235 ) zu verwenden
mattavatar
11

Da niemand erwähnt hat - nicht genau das gleiche wie die Value(oder TestCase) Attribute von NUnit , aber MSTest hat DataSourceAttribute, mit denen Sie ähnliche Dinge tun können. Sie können es an eine Datenbank oder eine XML-Datei anschließen - nicht so einfach wie die Funktion von NUnit, erledigt aber die Aufgabe.

km
quelle
7

MSTest verfügt über ein leistungsstarkes Attribut namens DataSource . Mit diesem Attribut können Sie nach Bedarf einen datengesteuerten Test durchführen. Sie können Ihre Testdaten in XML, CSV oder in einer Datenbank haben. Hier sind einige Links, die Sie führen

http://visualstudiomagazine.com/articles/2009/09/15/unit-testing-with-vsts2008-part-3.aspx http://msdn.microsoft.com/en-us/library/ms182527.aspx
http: //msdn.microsoft.com/en-us/library/ms243192.aspx

Hoffe das wird dir helfen.

Pritam Karmakar
quelle
6

Es ist sehr einfach zu implementieren - Sie sollten TestContextEigenschaft und verwenden TestPropertyAttribute.

Beispiel

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

BEARBEITEN:

Ich habe einige Erweiterungsmethoden vorbereitet, um den Zugriff auf die TestContextImmobilie zu vereinfachen und so zu handeln, als hätten wir mehrere Testfälle. Siehe Beispiel zur Verarbeitung einfacher Testeigenschaften hier:

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

und Beispiel zum Erstellen komplexer Testobjekte:

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

Werfen Sie einen Blick auf die Erweiterung Methoden und eine Reihe von Proben für weitere Details.

Andrey Burykin
quelle
2
Dieser Ansatz funktioniert, erstellt jedoch nicht für jeden Parametersatz einzelne Testfälle.
usr4896260
Sie können etwas Komplexeres als TestProperty-Wert (z. B. "0-100") verwenden, analysieren und im Testkörper verarbeiten.
Andrey Burykin
4

Es gibt natürlich eine andere Möglichkeit, dies zu tun, die in diesem Thread nicht behandelt wurde, nämlich die Vererbung der Klasse, die die TestMethod enthält. Im folgenden Beispiel wurde nur eine Testmethode definiert, es wurden jedoch zwei Testfälle erstellt.

In Visual Studio 2012 werden zwei Tests im TestExplorer erstellt:

  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) { }
    }
Soumya Dutta
quelle
3

Ich konnte The DataRowAttributein Visual Studio 2015 nicht zum Laufen bringen. Am Ende hatte ich Folgendes:

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

Die wirkliche Lösung besteht darin, nur NUnit zu verwenden (es sei denn, Sie stecken in MSTest fest, wie ich es in diesem speziellen Fall bin).

Brandon
quelle
3
Sie sollten jeden Testaufruf in einen separaten Test aufteilen, um Zeit zu sparen, wenn einer von ihnen unterbrochen wird. (was wir alle wissen, wird passieren)
Silber
Ja natürlich. In der Praxis würde das so gemacht werden. In diesem Fall habe ich es der Einfachheit halber nur illustriert
Brandon