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...