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);  
     }  
 }  
tjjjohnson
źródło
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
1
Spróbuj DataRow(), zobacz: blogs.msdn.microsoft.com/devops/2016/06/17/…
Babak

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

khlr
źródło
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);
        }
    }
}
Thwaitesy
źródło
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 .

Gary.Ray
źródło
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.

Sztuka
źródło
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.

CindyH
źródło