Concept: Modules de remplacement
Ces instructions décrivent comment créer un module de remplacement qui peut être utilisé en tant que marque de réservation pour les composants qui doivent être développés. Un module de remplacement est un composant qui ne fait rien d'autre que de se déclarer et de déclarer les paramètres qu'il accepte. Un module de remplacement contient juste assez de code pour pouvoir être compilé et lié au reste des composants.
Relations
Eléments connexes
Description principale

Introduction

Un composant est testé en envoyant des entrées à son interface, puis en attendant qu'il les traite et en vérifiant les résultats. Lors du traitement, un composant a de forte chances d'utiliser d'autres composants en leur envoyant des entrées et en utilisant leurs résultats :

Diagramme décrit dans le texte d'accompagnement.

Fig1 : Test d'un composant que vous avez implémenté

Ces autres composants peuvent vous poser problème pour votre test :

  1. Il se peut qu'ils ne soient pas encore implémentés.
  2. Ils peuvent entraîner des incidents qui empêchent le test de fonctionner ou vous font perdre beaucoup de temps avant de vous rendre compte que l'échec du test n'a pas été causé par votre composant.
  3. Ils peuvent rendre difficile l'exécution des tests dont vous avez besoin. Si le composant est une base de données commerciale, votre société peut ne pas avoir assez de licences flottantes pour tout le monde. Il se peut aussi que l'un des composants soit du matériel qui ne soit disponible qu'à des heures définies dans un laboratoire séparé.
  4. Ils peuvent ralentir vos tests de sorte que ceux-ci ne sont pas assez souvent exécutés. L'initialisation de la base de données, par exemple, peut prendre cinq minutes par test.
  5. Il peut être difficile de forcer les composants à produire certains résultats. Vous voulez, par exemple, que chaque méthode qui écrit dans le disque traite les erreurs "disque plein". Comment pouvez-vous être sûr que le disque se remplit juste au moment où une méthode est appelée ?

Afin d'éviter ce genre de problèmes, vous pouvez décider d'utiliser des composants module de remplacement (aussi appelés objets factices). Les composants module de remplacement se comportent comme les composants réels, du moins en ce qui concerne les valeurs que votre composant leur envoie en exécutant ses tests. Ils peuvent aller plus loin : ils peuvent être des émulateurs génériques qui cherchent à reproduire fidèlement la plupart ou tous les comportements du composant. Il est souvent judicieux, par exemple, de construire des émulateurs logiciels pour le matériel. Ils se comportent comme le matériel mais fonctionnent un peu plus lentement. Ils sont utiles car ils supportent mieux le débogage, leurs copies disponibles sont plus nombreuses et on peut les utiliser avant que le matériel ait terminé.

Diagramme décrit dans le texte d'accompagnement.

Fig2 : Test d'un composant que vous avez implémenté en 'simulant' un composant dont il dépend

Les modules de remplacement ont deux inconvénients.

  1. Ils peuvent être chers à la construction. (C'est le cas en particulier des émulateurs.) Etant eux-mêmes des logiciels, ils ont besoin de maintenance.
  2. Ils peuvent masquer des erreurs. Supposez, par exemple, que votre composant utilise des fonctions de trigonométrie mais qu'aucune bibliothèque ne soit encore disponible. Vos trois jeux de test demandent les sinus de trois angles : 10 degrés, 45 degrés et 90 degrés. Vous prenez votre calculatrice pour obtenir les valeurs exactes, qui sont 0,173648178, 0,707106781 et 1,0 respectivement et construisez un module de remplacement pour celles-ci. Tout se passe bien jusqu'à ce que vous intégriez la bibliothèque trigonométrique réelle dont les paramètres effectifs de la fonction sinus sont en radiant et qui donne alors comme résultat -0,544021111, 0,850903525, et 0,893996664. Il s'agit d'une erreur dans votre code qui est découvert plus tard, et a demandé plus d'efforts, que vous n'auriez voulu.

Modules de remplacement et pratiques de conception logicielle

A moins qu'ils n'aient été construits parce que le composant réel n'était pas encore disponible, vous conserverez vos modules de remplacement au-delà du déploiement. Les tests qu'ils supportent risquent d'être importants lors de la maintenance du produit. Il faut donc écrire les modules de remplacement de manière plus formelle qu'un code jetable. Bien qu'ils n'aient pas besoin de répondre aux normes du code du produit (la plupart n'ont par exemple pas besoin d'une suite de tests qui leur soit propre), les développeurs de logiciels devront les maintenir en tant que composants du changement du produit. Si cette maintenance s'avère trop difficile, les modules de remplacement seront éliminés et l'investissement sera perdu.

Les modules de remplacement affectent la conception des composants, en particulier lorsqu'ils doivent être conservés. Supposez, par exemple, que votre composant utilise une base de données pour stocker de façon permanente des paires clé/valeur. Considérez deux scénarios de conception :

Scénario 1 : la base de données est aussi bien utilisée pour les tests que pour une utilisation normale. L'existence de la base de données n'a pas besoin d'être cachée au composant. Vous pourriez l'initialiser avec le nom de la base de données :

 public Component(

String databaseURL) { try {     databaseConnection =         DriverManager.getConnection(databaseURL);     ... } catch (SQLException e) {...}     }

Bien que vous ne souhaitiez pas que chaque localisation lisant ou écrivant une valeur construise une instruction SQL, vous aurez certainement des méthodes qui contiendront du SQL. Par exemple, un code de composant ayant besoin d'une valeur peut appeler cette méthode de composant :
 public String get(String key) { try {     Statement stmt =       databaseConnection.createStatement();     ResultSet rs = stmt.executeQuery(       

"SELECT value FROM Table1 WHERE key=" + key);     ... } catch (SQLException e) {...}     }

Scénario 2 : la base de données est remplacée pour le test par un module de remplacement. Le code du composant doit être le même, qu'il fonctionne pour la base de données réelle ou pour le module de remplacement. Il doit donc être codé pour utiliser les méthodes d'une interface abstraite :
 

interface KeyValuePairs { String 

get(String key); void 

put(String key, String value);     }

Les tests implémenteraient KeyValuePairs avec un élément simple comme une table de hachage :
 

class FakeDatabase implements KeyValuePairs  { Hashtable table = new Hashtable(); public String 

get(String key) {     return (String) table.get(key); } public void 

put(String key, String value) {     table.put(key, value); }     }
Lorsqu'il n'est pas utilisé dans un test, un composant utilise un objet adaptateur qui a converti les appels vers l'interface KeyValuePairs dans les instructions SQL :
 

class DatabaseAdapter implements KeyValuePairs { private Connection databaseConnection; public DatabaseAdapter(String databaseURL) {     try {         databaseConnection =             DriverManager.getConnection(databaseURL);         ...     } catch (SQLException e) {...} } public String 

get(String key) {     try {         Statement stmt =            databaseConnection.createStatement();         ResultSet rs = stmt.executeQuery(           "SELECT value FROM Table1 WHERE key=" + key);         ...     } catch (SQLException e) {...} } public void 

put(String key, String value) {     ... }     }

Votre composant peut n'avoir qu'un seul constructeur pour les tests et les autres clients. Ce constructeur peut prendre un objet qui implémente KeyValuePairs. Il peut aussi fournir cette interface pour les tests uniquement, requérant que les clients habituels du composant fassent passer le nom d'une base de données :
 class Component { 

public Component(String databaseURL) {     this.valueStash = new DatabaseAdapter(databaseURL); } // For testing. 

protégé Component(KeyValuePairs valueStash) {     this.valueStash = valueStash; }     }

Du point de vue des programmeurs client, les deux scénarios de conception donnent la même API, mais l'un est plus facile à tester que l'autre. (Notez bien que certains tests peuvent utiliser la base de données réelle et d'autres, la base de données module de remplacement.)

Informations supplémentaires


Pour plus d'informations concernant les modules de remplacement, voir :