MSTest a-t-il un équivalent au TestCase de NUnit?

107

Je trouve la TestCasefonctionnalité de NUnit assez utile comme moyen rapide de spécifier les paramètres de test sans avoir besoin d'une méthode distincte pour chaque test. Y a-t-il quelque chose de similaire dans 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
la source
Question similaire voir stackoverflow.com/questions/347535/how-to-rowtest-with-mstest/...
Michael Freidgeim
Pourquoi n'utilisez-vous pas NUnit?
Mike de Klerk du
1
@MikedeKlerk: Nunit est incroyablement lent si vous utilisez Entity Framework ... Il reflète apparemment toutes vos classes générées chaque fois que vous exécutez un test.
Robert Harvey
De manière générale, NUnit a plus de fonctionnalités que MSTest, si vous utilisez MSTest juste pour pouvoir exécuter vos tests avec VS Test Explorer, vous pouvez faire de même avec NUnit en installant l'extension NUnit Test Adapter via NuGet
Stacked
1
Essayez DataRow(), voir: blogs.msdn.microsoft.com/devops/2016/06/17/…
Babak

Réponses:

62

Microsoft a récemment annoncé "MSTest V2" (voir article de blog ). Cela vous permet d'utiliser de manière cohérente (bureau, UWP, ...) l' DataRowattribut -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);  
     }  
 } 

Encore une fois, l'Explorateur de tests de Visual Studio Express ne reconnaît malheureusement pas ces tests. Mais au moins les versions VS «complètes» prennent désormais en charge cette fonctionnalité!

Pour l'utiliser, installez simplement les packages NuGet MSTest.TestFramework et MSTest.TestAdapter (tous deux en version préliminaire à partir de maintenant).

Réponse plus ancienne:

Si vous n'êtes pas obligé de vous en tenir à MSTest et que vous l'utilisez simplement pour pouvoir exécuter les tests via l'Explorateur de tests car vous n'avez qu'une édition de Visual Studio Express, alors cela pourrait être une solution pour vous:

Il existe l'extension VsTestAdapter VSIX pour pouvoir exécuter des tests NUnit via l'Explorateur de tests. Malheureusement, les utilisateurs de VS Express ne peuvent pas installer d'extensions ... Mais heureusement, le VsTestAdapter est également livré avec un NuGet-Package !

Donc, si vous êtes un utilisateur VS Express, installez simplement le package NuGet VsTestAdapter et profitez de l'exécution de vos tests / cas de test NUnit via l'Explorateur de tests!


Malheureusement, la déclaration susmentionnée n'est pas vraie. S'il est parfaitement possible d'installer le package via une édition Express, cela ne sert à rien, car il ne peut pas utiliser l'Explorateur de tests. Il y a déjà eu une note latérale sur une ancienne version du TestAdapter, qui a été supprimée de la page de description de la 2.0.0 :

Notez que cela ne fonctionne pas avec VS Express

khlr
la source
4
MSTest "v2" est maintenant le framework par défaut lors de l'utilisation de VS 2017. Maintenant que cela sera pris en charge OOTB sur la dernière version, cette information devrait probablement aller en haut de la réponse.
Marc L.
34

Je sais que c'est une réponse tardive, mais j'espère que cela aidera les autres.

J'ai cherché partout une solution élégante et j'ai fini par en écrire une moi-même. Nous l'utilisons dans plus de 20 projets avec des milliers de tests unitaires et des centaines de milliers d'itérations. Jamais une seule fois manqué un battement.

https://github.com/Thwaitesy/MSTestHacks

1) Installez le package NuGet .

2) Héritez votre classe de test de TestBase

public class UnitTest1 : TestBase
{ }

3) Créez une propriété, un champ ou une méthode qui renvoie 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) Ajoutez l'attribut MSTest DataSource à votre méthode de test, en pointant vers le nom IEnumerable ci-dessus. Cela doit être pleinement qualifié.

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

    Assert.IsNotNull(number);
}

Résultat final: 3 itérations comme la DataSource normale :)

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
la source
Cela fonctionnerait-il également avec plusieurs paramètres pour chaque cas?
Lonefish
Étant donné qu'il y a eu une modification dans la bibliothèque sous-jacente, cela ne fonctionne pas avec MsTest "v2" . Il s'agit de la valeur par défaut pour VS15 (VS 2017).
Marc L.
3
Oui, si vous utilisez MSTest V2, il existe un nouveau fournisseur de cas de test similaire à celui de NUnit. Donc pas besoin de ce travail autour de 👏
Thwaitesy
Cela ne semble pas fonctionner dans VS 2015, le fichier de configuration de l'application ne se remplit pas dynamiquement et les sources de données ne sont donc pas trouvées
Reed
13

Je sais que c'est une autre réponse tardive, mais dans mon équipe qui est verrouillée dans l'utilisation du framework MS Test, nous avons développé une technique qui repose uniquement sur les types anonymes pour contenir un tableau de données de test, et LINQ pour parcourir et tester chaque ligne. Il ne nécessite aucune classe ou framework supplémentaire et a tendance à être assez facile à lire et à comprendre. Il est également beaucoup plus facile à mettre en œuvre que les tests basés sur les données utilisant des fichiers externes ou une base de données connectée.

Par exemple, disons que vous avez une méthode d'extension comme celle-ci:

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

Vous pouvez utiliser un tableau de types anonymes combiné à LINQ pour écrire un test comme celui-ci:

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

Lors de l'utilisation de cette technique, il est utile d'utiliser un message formaté qui inclut les données d'entrée dans l'Assert pour vous aider à identifier la ligne qui entraîne l'échec du test.

J'ai blogué sur cette solution avec plus d'informations et de détails sur AgileCoder.net .

Gary Ray
la source
4
Le plus gros problème avec ceci est que si un cas échoue hors du tableau de valeurs, le test entier échoue et aucun cas n'est testé.
ytoledano
Cela crée des cas de test qui peuvent s'influencer mutuellement.
BartoszKP
@BartoszKP Uniquement si le système testé a des effets secondaires, auquel cas ce n'est probablement pas une technique optimale.
Gary Ray
@ Gary.Ray Aussi lorsque le système n'a pas encore d' effets secondaires . Aussi lorsqu'un test échoue et qu'un autre développeur essaie de résoudre ce problème, et perd des heures à essayer de déterminer si la dépendance est importante ou non. C'est juste quelque chose que vous ne devriez jamais faire, point final.
BartoszKP
Assez bien. +1
Trey Mack
7

Khlr a donné de bonnes explications détaillées et apparemment, cette approche a commencé à fonctionner dans VS2015 Express for Desktop. J'ai essayé de laisser le commentaire, mais mon manque de réputation ne m'a pas permis de le faire.

Permettez-moi de copier la solution ici:

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

Pour l'utiliser, installez simplement les packages NuGet MSTest.TestFramework et MSTest.TestAdapter .

Un problème est

Erreur CS0433 Le type «TestClassAttribute» existe à la fois dans «Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version = 10.0.0.0 et« Microsoft.VisualStudio.TestPlatform.TestFramework, Version = 14.0.0.0

Donc, veuillez supprimer Microsoft.VisualStudio.QualityTools.UnitTestFramework des références du projet.

Vous êtes les bienvenus pour modifier la réponse originale et supprimer celle-ci.

Art
la source
0

MSTest a l'attribut DataSource, qui vous permettra de lui alimenter une table de base de données, csv, xml, etc. Je l'ai utilisé et cela fonctionne bien. Je ne connais pas de moyen de placer les données juste au-dessus en tant qu'attributs comme dans votre question, mais il est très facile de configurer les sources de données externes et les fichiers peuvent être inclus dans le projet. Je l'ai fait fonctionner une heure après mes débuts et je ne suis pas un expert en tests automatisés.

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 propose un didacticiel complet basé sur l'entrée de la base de données.

http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ a un tutoriel basé sur l'entrée de fichier XML.

CindyH
la source