Czy MSTest ma odpowiednik TestCase NUnit?


107

Uważam, że TestCasefunkcja w NUnit jest całkiem przydatna jako szybki sposób określenia parametrów testu bez konieczności stosowania oddzielnej metody dla każdego testu. Czy jest coś podobnego w 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);  
     }  
 }  


Dlaczego nie używasz NUnit?
— Mike de Klerk

1
@MikedeKlerk: Nunit działa niewiarygodnie wolno, jeśli używasz Entity Framework ... Najwyraźniej odzwierciedla wszystkie wygenerowane przez Ciebie klasy za każdym razem, gdy uruchamiasz test.
— Robert Harvey

Ogólnie rzecz biorąc, NUnit ma więcej funkcji niż MSTest, jeśli używasz MSTest tylko po to, aby móc przeprowadzić testy za pomocą VS Test Explorer, możesz zrobić to samo z NUnit, instalując rozszerzenie NUnit Test Adapter przez NuGet
— Stacked

Odpowiedzi:


62

Firma Microsoft niedawno ogłosiła „MSTest V2” (zobacz artykuł na blogu ). Dzięki temu możesz konsekwentnie (komputer stacjonarny, UWP, ...) używać opcji DataRow-attribute!

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

Niestety, Eksplorator testów programu Visual Studio Express nie rozpoznaje tych testów. Ale przynajmniej „pełne” wersje VS obsługują teraz tę funkcję!

Aby go użyć, po prostu zainstaluj pakiety NuGet MSTest.TestFramework i MSTest.TestAdapter (oba w wersji wstępnej od teraz).

Starsza odpowiedź:

Jeśli nie musisz trzymać się MSTest i używasz go po prostu do uruchamiania testów za pomocą Eksploratora testów ponieważ masz tylko wersję Visual Studio Express, to może być rozwiązanie dla Ciebie:

Istnieje rozszerzenie VsTestAdapter VSIX umożliwiające uruchamianie testów NUnit za pośrednictwem Eksploratora testów. Niestety, użytkownicy VS Express nie mogą instalować rozszerzeń ... Ale na szczęście VsTestAdapter jest również dostarczany z prostym pakietem NuGet !

Tak więc, jeśli jesteś użytkownikiem VS Express, po prostu zainstaluj VsTestAdapter NuGet-Package i ciesz się uruchamianiem testów / przypadków testowych NUnit za pośrednictwem Eksploratora testów!


Niestety powyższe stwierdzenie nie jest prawdziwe. Chociaż jest całkowicie możliwe zainstalowanie pakietu za pośrednictwem edycji Express, jest to bezużyteczne, ponieważ nie może korzystać z Eksploratora testów. Wcześniej była uwaga dodatkowa na temat starszej wersji TestAdapter, która została usunięta ze strony opisu wersji 2.0.0 :

Zwróć uwagę, że nie działa z VS Express


4
MSTest "v2" jest teraz domyślnym frameworkiem podczas korzystania z VS 2017. Teraz, gdy będzie to obsługiwane OOTB w najnowszej wersji, ta informacja powinna prawdopodobnie znaleźć się na początku odpowiedzi.
— Marc L.

34

Wiem, że to późna odpowiedź, ale mam nadzieję, że pomoże to innym.

Wszędzie szukałem eleganckiego rozwiązania i sam je napisałem. Używamy go w ponad 20 projektach z tysiącami testów jednostkowych i setkami tysięcy iteracji. Ani razu nie przegapiłam.

https://github.com/Thwaitesy/MSTestHacks

1) Zainstaluj pakiet NuGet .

2) Dziedzicz klasę testową z TestBase

public class UnitTest1 : TestBase
{ }

3) Utwórz właściwość, pole lub metodę, która zwraca wartość 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) Dodaj atrybut MSTest DataSource do metody testowej, wskazując na powyższą nazwę IEnumerable. To musi być w pełni kwalifikowane.

[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
    var number = this.TestContext.GetRuntimeDataSourceObject<int>();

    Assert.IsNotNull(number);
}

Wynik końcowy: 3 iteracje, tak jak normalne źródło danych :)

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

Czy zadziałałoby to również z wieloma parametrami dla każdego przypadku?
— Lonefish

Ponieważ nastąpiła zmiana w podstawowej bibliotece, nie działa to z MsTest „v2” . Jest to ustawienie domyślne dla VS15 (VS 2017).
— Marc L.

3
Tak, jeśli używasz MSTest V2, istnieje nowy dostawca przypadków testowych, który jest podobny do NUnit. Tak więc nie ma potrzeby, aby to obejść 👏
— Thwaitesy

Wydaje się, że to nie działa w VS 2015, plik konfiguracyjny aplikacji nie wypełnia się dynamicznie, a zatem nie znaleziono źródeł danych
— Reed

13

Wiem, że to kolejna późna odpowiedź, ale w moim zespole, który jest zablokowany przy użyciu frameworka MS Test, opracowaliśmy technikę, która opiera się tylko na typach anonimowych do przechowywania tablicy danych testowych i LINQ do zapętlania i testowania każdego wiersza. Nie wymaga żadnych dodatkowych klas ani ram i wydaje się być dość łatwe do odczytania i zrozumienia. Jest również znacznie łatwiejszy do wdrożenia niż testy oparte na danych z wykorzystaniem plików zewnętrznych lub połączonej bazy danych.

Załóżmy na przykład, że masz taką metodę rozszerzenia:

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

Możesz użyć i tablicy typów anonimowych połączonych z LINQ, aby napisać takie testy:

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

Korzystając z tej techniki, warto użyć sformatowanego komunikatu, który zawiera dane wejściowe w Assert, aby pomóc Ci zidentyfikować wiersz powodujący niepowodzenie testu.

Opisałem to rozwiązanie na blogu AgileCoder.net, podając więcej informacji i szczegółów .


4
Największym problemem jest to, że jeśli jakikolwiek przypadek zakończy się niepowodzeniem z tablicy wartości - cały test kończy się niepowodzeniem i nie są testowane żadne inne przypadki.
— ytoledano

Tworzy to przypadki testowe, które mogą na siebie wpływać.
— BartoszKP

@BartoszKP Tylko jeśli testowany system ma skutki uboczne, w takim przypadku prawdopodobnie nie jest to optymalna technika.
— Gary.Ray,

@ Gary.Ray Również wtedy, gdy system nie ma jeszcze efektów ubocznych . Również wtedy, gdy test się nie powiedzie, a inny programista próbuje to naprawić i marnuje godziny na próbę ustalenia, czy zależność ma znaczenie, czy nie. To jest coś, czego nigdy nie powinieneś robić, kropka.
— BartoszKP

Wystarczająco dobry. +1
— Trey Mack,

7

Khlr podał dobre szczegółowe wyjaśnienia i najwyraźniej to podejście zaczęło działać w VS2015 Express for Desktop. Próbowałem zostawić komentarz, ale mój brak reputacji nie pozwolił mi na to.

Skopiuję rozwiązanie tutaj:

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

Aby z niego skorzystać, wystarczy zainstalować pakiety NuGet MSTest.TestFramework i MSTest.TestAdapter .

Jest jeden problem

Błąd CS0433 Typ „TestClassAttribute” istnieje zarówno w „Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version = 10.0.0.0, jak i„ Microsoft.VisualStudio.TestPlatform.TestFramework, Version = 14.0.0.0

Dlatego usuń Microsoft.VisualStudio.QualityTools.UnitTestFramework z odniesień do projektu.

Serdecznie zapraszamy do edycji oryginalnej odpowiedzi i usunięcia tej.


0

MSTest ma atrybut DataSource, który pozwoli ci przesłać do niego tabelę bazy danych, csv, xml itp. Użyłem go i działa dobrze. Nie znam sposobu na umieszczenie danych powyżej jako atrybutów, jak w pytaniu, ale bardzo łatwo jest skonfigurować zewnętrzne źródła danych i pliki, które można uwzględnić w projekcie. Uruchomiłem go godzinę od kiedy zacząłem i nie jestem ekspertem od testów automatycznych.

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 zawiera pełny samouczek oparty na danych wejściowych z bazy danych.

http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ zawiera samouczek oparty na danych wejściowych w pliku XML.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.