MSTest ha un equivalente a TestCase di NUnit?


107

Trovo la TestCasefunzione in NUnit abbastanza utile come un modo rapido per specificare i parametri di test senza bisogno di un metodo separato per ogni test. C'è qualcosa di simile in 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);  
     }  
 }  


Perché non usi NUnit?
Mike de Klerk

1
@MikedeKlerk: Nunit è incredibilmente lento se stai usando Entity Framework ... Apparentemente si riflette su tutte le tue classi generate ogni volta che esegui un test.
Robert Harvey,

In generale, NUnit ha più funzionalità di MSTest, se utilizzi MSTest solo per poter eseguire i tuoi test con VS Test Explorer, puoi fare lo stesso con NUnit installando l'estensione NUnit Test Adapter tramite NuGet
Stacked

Risposte:


62

Microsoft ha recentemente annunciato "MSTest V2" (vedi articolo del blog ). Ciò consente di utilizzare in modo coerente (desktop, UWP, ...) l' DataRowattributo!

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

Anche in questo caso, Test Explorer di Visual Studio Express purtroppo non riconosce questi test. Ma almeno le versioni VS "complete" ora supportano questa funzione!

Per usarlo, installa semplicemente i pacchetti NuGet MSTest.TestFramework e MSTest.TestAdapter (entrambi pre-rilascio al momento).

Risposta precedente:

Se non devi restare con MSTest e lo stai usando solo per poter eseguire i test tramite Test Explorer perché hai solo un'edizione di Visual Studio Express, allora questa potrebbe essere una soluzione per te:

C'è l' estensione VSIX VsTestAdapter per essere in grado di eseguire test NUnit tramite Test Explorer. Sfortunatamente, gli utenti di VS Express non possono installare estensioni ... Ma fortunatamente VsTestAdapter viene fornito con un semplice pacchetto NuGet !

Quindi, se sei un utente VS Express, installa il pacchetto NuGet VsTestAdapter e divertiti a eseguire i tuoi test / casi di test NUnit tramite Esplora test!


Purtroppo l'affermazione di cui sopra non è vera. Sebbene sia perfettamente possibile installare il pacchetto tramite un'edizione Express, è inutile, poiché non può utilizzare Test Explorer. In precedenza c'era una nota a margine su una versione precedente del TestAdapter, che è stata rimossa dalla pagina di descrizione della 2.0.0 :

Nota che non funziona con VS Express


4
MSTest "v2" è ora il framework predefinito quando si utilizza VS 2017. Ora che questo sarà supportato da OOTB nell'ultima versione, queste informazioni dovrebbero probabilmente andare all'inizio della risposta.
Marc L.

34

So che questa è una risposta tardiva ma spero che aiuti gli altri.

Ho cercato ovunque una soluzione elegante e ho finito per scriverne una io stesso. Lo usiamo in oltre 20 progetti con migliaia di unit test e centinaia di migliaia di iterazioni. Mai una volta perso un colpo.

https://github.com/Thwaitesy/MSTestHacks

1) Installa il pacchetto NuGet .

2) Eredita la tua classe di test da TestBase

public class UnitTest1 : TestBase
{ }

3) Creare una proprietà, un campo o un metodo che restituisca 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) Aggiungi l'attributo MSTest DataSource al tuo metodo di test, puntando di nuovo al nome IEnumerable sopra. Questo deve essere pienamente qualificato.

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

    Assert.IsNotNull(number);
}

Risultato finale: 3 iterazioni proprio come il normale DataSource :)

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

Funzionerebbe anche con più parametri per ogni caso?
Lonefish

Poiché è stata apportata una modifica nella libreria sottostante, ciò non funziona con MsTest "v2" . Questa è l'impostazione predefinita per VS15 (VS 2017).
Marc L.

3
Sì, se stai usando MSTest V2, c'è un nuovo fornitore di test case simile a NUnit. Quindi non c'è bisogno di questo lavoro intorno a 👏
Thwaitesy

Questo non sembra funzionare in VS 2015, il file di configurazione dell'app non viene popolato dinamicamente e quindi le origini dati non vengono trovate
Reed

13

So che questa è un'altra risposta tardiva, ma nel mio team che è bloccato nell'uso del framework MS Test, abbiamo sviluppato una tecnica che si basa solo su tipi anonimi per contenere una serie di dati di test e LINQ per eseguire il ciclo e testare ogni riga. Non richiede classi o framework aggiuntivi e tende ad essere abbastanza facile da leggere e comprendere. È anche molto più facile da implementare rispetto ai test basati sui dati utilizzando file esterni o un database connesso.

Ad esempio, supponi di avere un metodo di estensione come questo:

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

È possibile utilizzare una matrice di tipi anonimi combinati a LINQ per scrivere test come questo:

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

Quando si utilizza questa tecnica è utile utilizzare un messaggio formattato che includa i dati di input nell'assert per identificare la riga che causa il fallimento del test.

Ho scritto sul blog di questa soluzione con più background e dettagli su AgileCoder.net .


4
Il problema più grande con questo è che se un caso fallisce fuori dall'array di valori, l'intero test fallisce e non vengono testati altri casi.
ytoledano

Questo crea casi di test che possono influenzarsi a vicenda.
BartoszKP

@BartoszKP Solo se il sistema sotto test ha effetti collaterali, nel qual caso probabilmente questa non è una tecnica ottimale.
Gary

@ Gary.Ray Anche quando il sistema non ha ancora effetti collaterali . Anche quando un test non viene superato e un altro sviluppatore cerca di risolverlo e spreca ore a cercare di capire se la dipendenza è importante o meno. Questo è solo qualcosa che non dovresti mai fare, punto.
BartoszKP

Abbastanza buono. +1
Trey Mack

7

Khlr ha fornito una buona spiegazione dettagliata e apparentemente questo approccio ha iniziato a funzionare in VS2015 Express per desktop. Ho provato a lasciare il commento, ma la mia mancanza di reputazione non mi ha permesso di farlo.

Fammi copiare la soluzione qui:

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

Per usarlo, installa i pacchetti NuGet MSTest.TestFramework e MSTest.TestAdapter .

Un problema è

Errore CS0433 Il tipo "TestClassAttribute" esiste sia in "Microsoft.VisualStudio.QualityTools.UnitTestFramework, versione = 10.0.0.0 che in" Microsoft.VisualStudio.TestPlatform.TestFramework, versione = 14.0.0.0

Quindi, rimuovere Microsoft.VisualStudio.QualityTools.UnitTestFramework dai riferimenti del progetto.

Ti invitiamo a modificare la risposta originale ed eliminare questa.


0

MSTest ha l'attributo DataSource, che ti permetterà di alimentarlo con una tabella di database, csv, xml, ecc. L'ho usato e funziona bene. Non conosco un modo per inserire i dati proprio sopra come attributi come nella tua domanda, ma è molto facile impostare le origini dati esterne ei file possono essere inclusi nel progetto. L'ho fatto funzionare un'ora da quando ho iniziato e non sono un esperto di test automatizzati.

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 ha un tutorial completo basato sull'input del database.

http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ ha un tutorial basato sull'input di file XML.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.