Developpez.com - Microsoft DotNET
X

Choisissez d'abord la catégorieensuite la rubrique :


Les tests unitaires avec Visual Studio 2008

Date de publication : 08/11/2009 , Date de mise à jour : 08/11/2009

Par Ronald Vasseur (Autres articles) (Blog)
 


I. Introduction
II. Introduction
III. Exécuter des tests unitaires avec Visual Studio 2008
IV. Conclusion


I. Introduction

Au cours de cet article nous allons voir comment créer et utiliser vos tests unitaires à l'aide de Visual Studio 2008. Mais avant de rentrer dans les détails il est peut être nécessaire pour certains d'expliquer rapidement ce que sont les tests unitaires, qui les utilisent, comment ils fonctionnent, à quoi servent-ils?

Les tests unitaires sont des morceaux de code qui sont écris dans un seul but, exécuter des unités de code en vue de les tester. Pour être plus clair un test unitaire peut être une méthode exécutant une méthode de votre application en lui passant les paramètres nécessaires et en vérifiant le résultat retourné. Un test unitaire est considéré comme réussi si le résultat ou le comportement est conforme à ce qui a été écris dans ce même test. Un test unitaire peut être écris dans un langage différent de celui qui a été utilisé pour écrire le code à tester.
Un test unitaire à pour mission de vérifier que le code écris ne comporte pas de bug et qu'il ne souffre pas de régression dans le temps suite à des modifications ultérieures comme des corrections de bugs ou des évolutions qui peuvent parfois avoir des effets de bords difficilement identifiables sans test précis.

Un test unitaire doit être exécutable automatiquement et cela de manière répétée, ainsi les tests unitaires pourront être exécutés fréquemment afin de vérifier qu'il n'y à pas de régression dans le temps.

Quand on parle de tests unitaires avec .Net le nom qui revient le plus fréquemment est NUnit qui est un Framework de test. Ce Framework permet d'écrire et d'exécuter des tests unitaires, il offre de nombreuses fonctionnalités qui en font certainement l'outil le plus aboutit pour la plateforme .Net, notons au passage qu'il est entièrement gratuit et libre d'utilisation. Cependant dans cet article je vais présenter les fonctionnalités de test unitaire offertes par Visual Studio 2008, qui permet de couvrir de nombreux cas et possède l'avantage d'être totalement intégré dans l'IDE et de pouvoir êtres exécutés sur un serveur au travers de Team Foundation Server. Pour information je suis en train de préparer un nouvel article sur les possibilités offertes par Visual Studio 2010 en la matière, celui-ci devrait être prêt au début de l'année 2010, en attendant voyons déjà ce que nous offre la version 2008 de l'IDE de Microsoft.

Les tests unitaires offrent un sujet idéal pour les discussions entre développeurs : perte de temps, indispensables, obligatoires, utiles, futiles? Avanat tout il s'agit de savoir quelle méthode de développement est la meilleure pour vous. De l'Extreme Programming (XP) au Test Driven Development (TDD) les tests unitaires trouvent une place et une fonction différentes à vous de voir celle qui vous convient le mieux et surtout celle que l'on vous impose, en effet dans la vie réelle le développeur ne fait souvent pas de tels choix.


II. Introduction

Tout d'abord pour créer et exécuter des tests unitaires avec Visual Studio 2008 vous devez avoir une version " Team Suite " ou " Test Edition ". Les tests unitaires sont totalement intégrés dans l'environnement de développement, nous allons voir comment les créer par le biais d'un assistant ou manuellement.

Visual Studio 2008 rend la création de tests unitaires très simple, prenons par exemple une classe SuperClass qui contient trois méthodes : Addition, Multiplication et Soustraction. Elles prennent toutes deux double en paramètres et retournent un double comme résultat. Voici le code de la classe qui va nous servir d'exemple :
Code de la classe à tester

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SuperNamespace
{
    public class SuperMath
    {
        public double Addition(double a, double b)
        {
            return a + b;
        }

        public double Multiplication(double a, double b)
        {
            return a * b;
        }

        public double Soustraction(double a, double b)
        {
            return a - b;
        }
    }
}

Voici maintenant comment générer la structure des tests :
Placez-vous avec la souris au dessus du code de votre classe puis faites un clic droit. Choisissez "Create Unit Test".

Création des tests
Création des tests

Une liste des classes et méthodes organisées par namespace est affichée, il faut alors sélectionner les éléments pour lesquels que l'on souhaite réaliser des tests unitaires. Apres avoir effectué la sélection il suffit de cliquer sur "OK".

Sélection des méthodes
Sélection des méthodes

Si nécessaire il est possible de modifier les paramètres de génération en cliquant sur le bouton "Settings". La capture suivante montre les paramètres modifiables au travers de cet écran :

Paramètres
Paramètres

A la suite de la sélection des éléments pour lesquels vous souhaitez générer des tests un nouveau projet (par défaut en C#) de test est ajouté à la solution. Il contient une classe possédant deux méthodes de tests pour tester unitairement la méthode Addition et Multiplication. Voici le code de test :
Code des tests générés

using SuperNamespace;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace SuperTests
{
    
    
    /// <summary>
    ///This is a test class for SuperMathTest and is intended
    ///to contain all SuperMathTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SuperMathTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Multiplication
        ///</summary>
        [TestMethod()]
        public void MultiplicationTest()
        {
            SuperMath target = new SuperMath(); // TODO: Initialize to an appropriate value
            double a = 0F; // TODO: Initialize to an appropriate value
            double b = 0F; // TODO: Initialize to an appropriate value
            double expected = 0F; // TODO: Initialize to an appropriate value
            double actual;
            actual = target.Multiplication(a, b);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        /// <summary>
        ///A test for Addition
        ///</summary>
        [TestMethod()]
        public void AdditionTest()
        {
            SuperMath target = new SuperMath(); // TODO: Initialize to an appropriate value
            double a = 0F; // TODO: Initialize to an appropriate value
            double b = 0F; // TODO: Initialize to an appropriate value
            double expected = 0F; // TODO: Initialize to an appropriate value
            double actual;
            actual = target.Addition(a, b);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        /// <summary>
        ///A test for Soustraction
        ///</summary>
        [TestMethod()]
        public void SoustractionTest()
        {
            SuperMath target = new SuperMath(); // TODO: Initialize to an appropriate value
            double a = 0F; // TODO: Initialize to an appropriate value
            double b = 0F; // TODO: Initialize to an appropriate value
            double expected = 0F; // TODO: Initialize to an appropriate value
            double actual;
            actual = target.Soustraction(a, b);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }
    }
}

Les tests ne sont pas exécutables en l'état, on peut le voir au travers des commentaires insérés dans le code. Il va falloir fournir une valeur pour chacun des paramètres ainsi qu'une valeur pour le résultat. Ainsi lors de l'exécution du test le résultat obtenu sera comparé au résultat attendu, si le résultat est le même alors le test aura réussi, sinon il aura échoué. Il faut également penser à supprimer la ligne Assert.Inconclusive(?) qui en l'état va rendre le test infructueux pour forcer le développeur à vérifier la logique du test ; il est possible de ne pas insérer cette ligne en choisissant l'option relative dans les paramètres de génération des tests. Pour notre tests on voit que l'assertion qui correspond le mieux est AreEqual() qui va comparer la valeur obtenue et la valeur espérée ; mais en fonction du contexte il est possible de choisir les conditions parmi une longue liste d'assertion qui permettent de définir de nombreux scénarios de tests. Voici le code permettant de tester unitairement la méthode addition, soustraction et la méthode multiplication :
Tests unitaires

using SuperNamespace;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace SuperTests
{
    
    
    /// <summary>
    ///This is a test class for SuperMathTest and is intended
    ///to contain all SuperMathTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SuperMathTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Multiplication
        ///</summary>
        [TestMethod()]
        public void MultiplicationTest()
        {
            SuperMath target = new SuperMath();
            double a = 2.5F;
            double b = 10F;
            double expected = 25F;
            double actual;
            actual = target.Multiplication(a, b);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Soustraction
        ///</summary>
        [TestMethod()]
        public void SoustractionTest()
        {
            SuperMath target = new SuperMath();
            double a = 10F;
            double b = 5F;
            double expected = 5F;
            double actual;
            actual = target.Soustraction(a, b);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Addition
        ///</summary>
        [TestMethod()]
        public void AdditionTest()
        {
            SuperMath target = new SuperMath();
            double a = 77F;
            double b = 200F;
            double expected = 277F;
            double actual;
            actual = target.Addition(a, b);
            Assert.AreEqual(expected, actual);
        }
    }
}

III. Exécuter des tests unitaires avec Visual Studio 2008

Maintenant que nous savons générer la structure de nos tests ainsi qu'écrire le test lui-même voici comment exécuter les tests unitaires :

Il existe divers chemins et raccourcis clavier pour exécuter les tests de notre solution, en voici une : à partir du menu Test, aller dans le sous-menu Run puis choisir en fonction des besoins :

Exécution des tests
Exécution des tests

"Tests in current context" ou "All tests in Solution". Visual Studio va alors compiler l'assembly du projet de test, puis exécuter un à un les différents tests. Les résultats seront alors affichés dans une fenêtre dédiée comme le montre la capture suivante :

Résultats des tests
Résultats des tests

Si l'exécution des tests unitaires est un succès alors une petite icône verte sera affichée en face de chacun d'eux ainsi que le libellé "Passed". Les tests pourront être également en état "Failed" ou même "Inconclusive" s'il n'a pas était possible de valider le succès du test.


IV. Conclusion

J'espère vous avoir montré la grande intégration des tests unitaires dans Visual Studio 2008 dans cette introduction aux tests avec l'IDE de Microsoft en version 2008. En cas de travail en équipe il peut être intéressant d'exécuter les tests sur un serveur de test/build et d'y associer une analyse de la couverture du code. Les fonctions de test de Visual Studio sont immensément plus larges que ce que l'on a pu voir dans cet article, il ne s'agissait que d'une introduction. Rendez-vous bientôt pour des articles plus complets, notamment sur les nouveautés en matières de test offertes par Visual Studio 2010.



Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2009 Ronald Vasseur. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Responsable bénévole de la rubrique Microsoft DotNET : Hinault Romaric -