Un framework de test est aux tests ce que l’IDE est au développement. Il fournit un environnement structuré permettant l’exécution de test et des méthodes pour aider au développement de ceux-ci.
Il existe plusieurs frameworks de test. Microsoft dispose de son framework,
mstest, qui est disponible dans les versions payantes de Visual Studio. Son intérêt est qu’il est fortement intégré à l’IDE. Son défaut est qu’il ne fonctionne pas avec les versions gratuites de l’environnement de développement. Comme nous sommes partis dans ce tutoriel avec la version gratuite, Visual C# Express, nous n’allons pas pouvoir utiliser
mstest.
Par contre, il existe d’autres framework de test, gratuits, comme le très connu
NUnit.
NUnit est la version .NET du framework
XUnit, qui se décline pour plusieurs environnements, avec par exemple
PHPUnit pour le langage PHP,
JUnit, pour java, etc.
Première chose à faire, installer
NUnit, pour cela, rendez-vous à cet emplacement pour le télécharger :
http://www.NUnit.org/?p=download. La version que j’utilise dans ce tutoriel est la version 2.5.10.
Démarrez l’installation :
L’installation est en anglais, mais assez facile à suivre. Cliquez sur
Next pour aller à l’écran suivant.
Après avoir accepté la licence, vous pouvez choisir l’installation classique :
À la fin de l’installation, nous pouvons voir que tout s’est bien passé :
Une fois le framework de test installé, nous pouvons créer un nouveau projet qui contiendra une fonctionnalité à tester. Je l’appelle
MaBibliothequeATester. D’une manière générale, nous allons surtout tester des assemblys avec
NUnit. Ici, je crée donc un projet de type bibliothèque de classes. Ce projet ne sera donc pas exécutable, car il ne s’agit pas d’une application console.
Et dedans, je vais pouvoir créer une classe utilitaire, disons
Math, qui contiendra notre fameuse méthode de calcul de factoriel :
Code : C# | public static class Math
{
public static int Factorielle(int a)
{
if (a <= 1)
return 1;
return a * Factorielle(a - 1);
}
}
|
Puis ajoutons un nouveau projet de type bibliothèque de classes où nous allons mettre nos tests unitaires, appelons le
MathTests.Unit. Ce n’est pas une norme absolue, mais je vous conseille de suffixer vos projets de test avec
.Unit, ce qui permet de les identifier facilement.
Les tests doivent se mettre dans une classe spéciale. Ici aussi, pas de règle de nommage obligatoire, mais il est intéressant d’avoir une norme pour facilement s’y retrouver. Je vous propose de nommer les classes de tests en commençant par le nom de la classe que l’on doit tester, suivie du mot
Tests. Ce qui donne :
MathTests.
Pour être reconnue par le framework de test, la classe doit respecter un certain nombre de contrainte. Elle doit dans un premier temps être décorée de l’attribut
[TestFixture]. Il s’agit d’un attribut qui permet à
NUnit de reconnaitre les classes qui contiennent des tests.
Cet attribut étant dans une assembly de
NUnit, vous devez rajouter une référence à l’assembly
NUnit.framework :
et inclure l’espace de nom adéquat :
Code : C#
Nous allons pouvoir créer des méthodes à l’intérieur de cette classe. De la même façon, une méthode pourra être reconnue comme une méthode de test si elle est décorée de l’attribut
[Test].
Ici aussi, il est intéressant de suivre une règle de nommage afin de pouvoir identifier rapidement l’intention de la méthode de test. Je vous propose le nommage suivant :
MethodeTestee_EtatInitial_EtatAttendu()
Par exemple, une méthode de test permettant de tester la factorielle pourrait s’appeler :
Code : C# | [TestFixture]
public class MathTests
{
[Test]
public void Factorielle_AvecValeur3_Retourne6()
{
// test à faire
}
}
|
Il existe plein d’autres attributs que vous découvrirez ultérieurement. Il est temps de passer à l’écriture du test et surtout à la vérification du résultat.
Pour cela, on utilise des méthodes de
NUnit qui nous permette de vérifier par exemple qu’une valeur est égale à une autre attendue. Cela se fait grâce à la méthode
Assert.AreEqual() :
Code : C# | [Test]
public void Factorielle_AvecValeur3_Retourne6()
{
int valeur = 3;
int resultat = MaBibliothequeATester.Math.Factorielle(valeur);
Assert.AreEqual(6, resultat);
}
|
Elle permet de vérifier que la variable valeur vaut bien 6.
Rajoutons tant qu’on y est une méthode de test qui échoue :
Code : C# | [Test]
public void Factorielle_AvecValeur10_Retourne1()
{
int valeur = 10;
int resultat = MaBibliothequeATester.Math.Factorielle(valeur);
Assert.AreEqual(1, resultat, "La valeur doit être égale à 1");
}
|
Il est important qu'une méthode de test ne s'occupe de tester qu'un seul cas d'une unique fonctionnalité, comme illustré juste au dessus. La première méthode teste la fonctionnalité Factorielle pour le cas où la valeur vaut 3 et la seconde s'occupe du cas où la valeur vaut 10. Vous pouvez rajouter autant de méthodes de tests que vous le souhaitez tant qu'elle sont décorée de l'attribut [Test].
J’en ai profité pour rajouter un message qui permettra d’indiquer des informations complémentaires si le test échoue.
Compilons maintenant notre projet et rendez-vous dans le répertoire d’installation de
NUnit (par défaut :
C:\Program Files\NUnit 2.5.10\bin\net-2.0) et lancez l’application
NUnit.exe :
La première chose à faire est de créer un nouveau projet :
Appelez-le
ProjetTest par exemple. Il faut ensuite ajouter une assembly de test, allez dans
Project >
Add Assembly :
Et allez pointer l’assembly de tests, à savoir
MathTests.Unit.dll.
NUnit analyse l’assembly et fait apparaitre la liste des tests qui composent notre assembly (en se basant sur les attributs
TestFixture et
Test) :
Nous pouvons à présent lancer les tests en cliquant sur
Run, et nous obtenons :
Ce qui nous permet de voir rapidement qu’il y a un test qui passe (icône verte) et un test qui échoue (icône rouge). Forcément, notre test n’était pas bon, il faut le réécrire. Nous voyons également qu’il nous indique que le résultat attendu était 1 alors que le résultat obtenu est de 3628800. Nous pouvons également voir le message que nous avons demandé d’afficher en cas d’erreur.
Le souci avec
NUnit, c’est qu’à partir du moment où il a chargé la dll pour lancer les tests, il n’est plus possible de faire des modifications, car toute tentative de compilation provoquera une erreur où il sera mentionné qu’il ne peut pas faire de modifications car le fichier est déjà utilisé ailleurs. Ce qui est vrai. Ce qui va nous obliger à fermer
NUnit et à le ré-ouvrir.
À noter que dans les versions payantes de Visual Studio, nous avons la possibilité de configurer
NUnit en tant qu’outil externe, ce que nous ne pouvons pas faire avec la version gratuite. Il va falloir faire avec… Tristesse de la gratuité…
Nous pouvons cependant un peu tricher en définissant un événement de post-compilation, qui consiste à lancer
NUnit automatiquement. Pour cela, allez dans les propriétés du projet, onglet événement de builds et tapez la commande suivante :
"C:\Program Files\NUnit 2.5.10\bin\net-2.0\NUnit.exe" $(TargetFileName)
Ici, nous indiquons qu'après la compilation, il va lancer le programme
NUnit.exe en prenant en paramètre le résultat de la compilation, représenté par la variable interne de Visual C# Express :
$(TargetFileName).
Par contre, cela veut dire que
NUnit va se lancer à chaque compilation, ce qui n’est peut-être pas le but recherché… Il faudra également fermer
NUnit avant de pouvoir faire quoi que soit d’autre.
À noter que maintenant que nous savons faire de l’introspection sur les méthodes et les attributs d’une classe, nous devrions être capables de créer une petite application qui exécute les tests automatiquement…
Pour en finir avec
NUnit, notons qu’il y a beaucoup de méthodes permettant de vérifier si un résultat est correct. Regardons les assertions suivantes :
Code : C# | bool b = true;
Assert.IsTrue(b);
string s = null;
Assert.IsNull(s);
int i = 10;
Assert.Greater(i, 6);
|
Elles parlent d’elles-mêmes. La première permet de vérifier qu’une condition est vraie. La deuxième permet de vérifier la nullité d’une variable. La dernière permet de vérifier que la variable est bien supérieure à une autre. À noter qu’elles ont chacune leur pendant (
IsFalse,
IsNotNull,
Less). En regardant la complétion automatique, vous découvrirez d’autres méthodes de vérification, mais celles-ci sont globalement suffisantes.
Nous pouvons également utiliser une syntaxe un peu plus parlante comme :
Code : C# | Assert.That(i, Is.EqualTo(10));
|
Mais cette syntaxe est peut-être un peu plus parlante aux anglophones…
Il est également possible d’utiliser un attribut pour vérifier qu’une méthode lève bien une exception, par exemple :
Code : C# | [Test]
[ExpectedException(typeof(FormatException))]
public void ToInt32_AvecChaineNonNumerique_LeveUneException()
{
Convert.ToInt32("abc");
}
|
Dans ce cas, le test passe si la méthode lève bien une
FormatException.
Avant de terminer, présentons deux attributs supplémentaires : les attributs
SetUp et
TearDown.
Ils permettent de décorer des méthodes qui seront appelées respectivement avant chaque test et après chaque test. C'est l'endroit idéal pour factoriser des initialisations ou des nettoyages dont dépendent tous les tests.
Code : C# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | [TestFixture]
public class MathTests
{
[SetUp]
public void InitialisationDesTests()
{
// rajouter les initialisations
}
[Test]
public void Factorielle_AvecValeur3_Retourne6()
{
// test à faire
}
[TearDown]
public void NettoyageDesTests()
{
// nettoyer les variables, ...
}
}
|
Il existe plein d’autres choses utiles à dire sur
NUnit, comme la description des autres attributs, ce que je ne vais pas faire ici. N’hésitez pas à aller voir sur internet des informations plus poussées pour approfondir votre maitrise des tests.