A bord de Salamanca

Aller au contenu | Aller au menu | Aller à la recherche

Tag - Visual Studio

Fil des billets - Fil des commentaires

Escale #3 : Tests unitaires

Nous avons maintenant une base de données à notre disposition. Mais ne perdons pas de vue le but de notre expédition, ou plutôt l'enchainement de buts : apprendre à utiliser Salamanca afin, in fine, de mettre en place un processus métier qui produit de la valeur.

Mais comme dans la fable du lièvre et de la tortue, nous prenons le temps de mettre en place des bonnes pratiques de développement en cours de route afin d'assurer à la fois la qualité de notre produit et la facilité de sa maintenance.

L'escale d'aujourd'hui s'attarde sur la mise en place des outils de contrôle de la qualité : les Tests.

Contexte

Même si nous parlons de tests unitaires, notre intention est plutôt de s'assurer que le code produit est conforme au résultat attendu, par exemple que les règles métier définies sont bien respectées. Dans la terminologie du test informatique, on parle alors de tests fonctionnels (de recette ou encore d'acceptation) par opposition aux tests techniques (unitaires, d'intégration, système, performance, ...).

Mais dans notre cas, nous nous appuyons sur le framework de test de Visual Studio. C'est pourquoi nous avons créé le projet Eproject.Tests lors de la mise en place de la solution (cf L'application Salamanca).

Configuration

Comme l'objet de notre application est de manipuler des données, nous avons besoin d'une base de données dédiée pour les tests qui puisse être recréée à chaque exécution d'un jeu de tests. Pour cela, nous procédons de la même manière que pour la base de données de développement, avec une étape supplémentaire :

  • création d'une base de données SQL Server 2008 Express
  • copie du fichier de base de données dans le projet de tests

Cette procédure peut se traduire sous forme de la commande batch CreateTests.cmd, placée dans le répertoire Create Scripts du projet Eproject.Sql :

SET CONNECT_STRING=.\SQLEXPRESS 
SET BASE_NAME=eProject_ABord_Tests
SET TestsDir=%CD%\..\..\Eproject.Tests

sqlcmd.exe -E -X -S %CONNECT_STRING% -v DatabaseName=%BASE_NAME% -i Create.sql

xcopy "C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\%BASE_NAME%.mdf" %TestsDir% /y
xcopy "C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\%BASE_NAME%_log.ldf" %TestsDir% /y

Une fois le fichier de base de données copié, nous l'ajoutons dans notre projet ("Afficher tous les fichiers", clic droit sur le fichier, puis "Inclure dans le projet").

La configuration de sa chaîne de connexion est facilité par l'utilisation du Data Application Block du framework Microsoft Enterprise Library (cf Pré-requis). Pour cela, nous utilisons :

  • un fichier de configuration app.config ajouté dans notre projet
  • l'utilitaire Enterprise Library Configuration

Enterprise Library Configuration

On obtient ainsi le code de configuration suivant :

<configuration> 
  <configSections>
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <dataConfiguration defaultDatabase="eProject_ABord_Tests" />
  <connectionStrings>
    <add name="eProject_ABord_Tests" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|eProject_ABord_Tests.mdf;User Instance=true"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

Codage

Pour pouvoir coder des tests qui manipulent des instances des entités métier que nous avons modélisé, nous aurons besoin d'une collection de DataMapper, dont le rôle (tel que je l'ai assimilé) est de servir de point d'ancrage de la couche de persistence, à savoir la gestion du cache et des échanges entre les instances d'objets en mémoire et leur structure de stockage en base de données (cf QuickStart : the Domain Model).

L'implémentation choisie est d'avoir une classe de base dont tous les tests hériterons. C'est une classe publique contenant une propriété de type DataMapperCollection avec un getter sous forme de singleton tirant parti des facilités offertes par les bibliothèques Enterprise Library et DataAccess pour créer une connexion avec la base de données (configurée par défaut dans app.config) ainsi qu'un mode de cache des données (dans notre cas, elles ne seront pas conservées en mémoire).

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Salamanca.DataAccess;
using Salamanca.DataAccess.Collections;
using NourY.Eproject.Model.Mappers.EnterpriseLibrary;

namespace NourY.Eproject.Tests
{
public class UnitTestBase
{
public UnitTestBase()
{
}

protected DataMapperCollection DataMappers
{
get
{
if (_DataMappers == null)
_DataMappers = Mappers.CreateDataMapperCollection(
DatabaseFactory.CreateDatabase(),
new NoCacheManager());
return _DataMappers;
}
}

private DataMapperCollection _DataMappers;
}

References

Pour pouvoir compiler notre projet, nous avons ajouté les références aux bibliothèques contenant les types utilisés dans notre classe de base :

  • DatabaseFactory dans EnterpriseLibrary.Data
  • NoCacheManager et DataMapperCollection dans DataAccess
  • Mappers dans Eproject.Model

 

Voici venu le temps de tester notre configuration à travers un exemple simple : je veux pouvoir sauvegarder le projet nommé "Projet Test" du client nommé "Client Test".

Nous ajoutons le test unitaire CrudProjetTest qui hérite de la classe UnitTestBase. Afin d'avoir une base de données "propre" à chaque exécution, nous l'associons à notre classe de test à travers l'attribut DeploymentItem.

    [TestClass]
[DeploymentItem("..\\eProject_ABord_Tests.mdf")]
public class CrudProjetTest : UnitTestBase
{
[TestMethod]
public void CanSaveProjet()
{
Client c = new Client(DataMappers);
c.Nom = "Projet Test";
Projet p = new Projet(c, DataMappers);
p.Nom = "Client Test";

Assert.IsTrue(p.IsModified);
p.Save();
Assert.IsFalse(p.IsModified);
}
}

Nous vous invitons à tester cette configuration dont le réel intérêt est à terme de pouvoir valider que l'implémentation des activités métier de notre application s'exécute avec succès et respectent les règles métier définis. Mais avant cela, nous verrons évidemment comment concevoir et coder les activités métier, concept essentiel de Salamanca...

Larguez les amarres !

Au moment de larguer les amarres, il y a toujours sur le quai un ami ou un passant pour nous demander si rien n'a été oublié et que tout a été chargé...

Pré-requis

Pour démarrer, nous avons bien sûr téléchargé la dernière version 1.0 (alpha) de Salamanca à l'adresse :

http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562

Suivant le manuel d'installation, nous avons d'abord vérifié que notre équipement contient déjà Visual Studio 2008 SP1 dont la version d'évaluation de l'édition Professionnal est téléchargeable à l'adresse :

http://www.microsoft.com/downloads/details.aspx?familyid=83C3A1EC-ED72-4A79-8961-25635DB0192B&displaylang=fr

Nous avons ensuite téléchargé et installé les Guidance Automation Extensions (GAX) à l'adresse :

http://www.microsoft.com/downloads/details.aspx?familyid=DF79C099-4753-4A59-91E3-5020D9714E4E

Comme nous souhaitons utiliser les facilités offertes par le Data Access Application Block, nous avons aussi téléchargé Enterprise Library 4.1 à l'adresse :

http://www.microsoft.com/Downloads/details.aspx?familyid=1643758B-2986-47F7-B529-3E41584B6CE5

Nous utiliserons également une base de données SQL Server 2008 Express disponible avec l'outil SQL Server 2008 Management Studio Express à l'adresse :

http://www.microsoft.com/downloads/details.aspx?displaylang=fr&FamilyID=7522a683-4cb2-454e-b908-e805e9bd4e28

L'application Salamanca

Nous voilà parés pour monter à bord de Salamanca. Notre périple commence par la création de notre application eProject dans notre environnement de développement Visual Studio.

Salamanca Application 

Nous respectons ensuite (presque) les conventions de nommage de mise en majuscule de notre langage préféré C# dans la définition du nom de domaine de l'application.

Salamanca Application Information  

Explorateur de solutions

Nous obtenons ainsi une solution Visual Studio constituée du projet Eproject.Model de type Bibliothèque de classes qui nous permettra de modéliser les concepts métier de notre application et de générer l'ensemble du code associé :

  • classes des entités métier
  • classes de mapping objet-relationnel (DataMappers)
  • scripts SQL de création des tables et procédures stockées de la base de données

Afin d'avoir les provisions nécessaires à notre voyage, nous ajoutons dés maintenant à la solution Visual Studio les projets pour chaque composant à fabriquer. Notre application Salamanca est alors composée de :

  1. Eproject.Model de type Bibliothèque de classes pour la modélisation et la génération des entités métier
  2. Eproject.Sql de type Projet de base de données pour la création et maintenance des scripts SQL
  3. Eproject.Tests de type Projet de test pour la création et l'exécution des tests unitaires
  4. Eproject.Activities de type Bibliothèque de classes pour le codage des activités métier
  5. Eproject.Web de type Application Web ASP.NET contenant l'implémentation web des activités ainsi que la définition de la présentation à travers :
    • une page maître
    • un thème ASP.NET
    • les ressources de localisation
  6. Eproject.Setup de type Projet d'installation Web pour le déploiement de l'application

Structure de base Subversion

Nous ajoutons l'arborescence des fichiers créés à partir de cette structure de base dans notre gestionnaire de versions (Subversion) qui sert de référentiel pour l'ensemble de nos codes sources.

Nous voilà munis d'un équipement bien outillé et d'un bel horizon devant nous.

Sun behind cloud

Lors de notre prochaine escale, vous verrez comment nous tirons profit du bon vent que nous amène la modélisation des entités et la génération du code associé.

Tâchons de garder le cap !