aboutsummaryrefslogtreecommitdiff
path: root/vendors/simpletest/docs/fr/mock_objects_documentation.html
diff options
context:
space:
mode:
Diffstat (limited to 'vendors/simpletest/docs/fr/mock_objects_documentation.html')
-rwxr-xr-xvendors/simpletest/docs/fr/mock_objects_documentation.html778
1 files changed, 778 insertions, 0 deletions
diff --git a/vendors/simpletest/docs/fr/mock_objects_documentation.html b/vendors/simpletest/docs/fr/mock_objects_documentation.html
new file mode 100755
index 000000000..c03ac611f
--- /dev/null
+++ b/vendors/simpletest/docs/fr/mock_objects_documentation.html
@@ -0,0 +1,778 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Documentation SimpleTest : les objets fantaise</title>
+<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
+</head>
+<body>
+<div class="menu_back"><div class="menu">
+<a href="index.html">SimpleTest</a>
+ |
+ <a href="overview.html">Overview</a>
+ |
+ <a href="unit_test_documentation.html">Unit tester</a>
+ |
+ <a href="group_test_documentation.html">Group tests</a>
+ |
+ <a href="mock_objects_documentation.html">Mock objects</a>
+ |
+ <a href="partial_mocks_documentation.html">Partial mocks</a>
+ |
+ <a href="reporter_documentation.html">Reporting</a>
+ |
+ <a href="expectation_documentation.html">Expectations</a>
+ |
+ <a href="web_tester_documentation.html">Web tester</a>
+ |
+ <a href="form_testing_documentation.html">Testing forms</a>
+ |
+ <a href="authentication_documentation.html">Authentication</a>
+ |
+ <a href="browser_documentation.html">Scriptable browser</a>
+</div></div>
+<h1>Documentation sur les objets fantaisie</h1>
+ This page...
+ <ul>
+<li>
+ <a href="#quoi">Que sont les objets fantaisie ?</a>
+ </li>
+<li>
+ <a href="#creation">Créer des objets fantaisie</a>.
+ </li>
+<li>
+ <a href="#bouchon">L'objet fantaisie - acteur</a> ou bouchon.
+ </li>
+<li>
+ <a href="#attentes">L'objet fantaisie - critique</a> avec des attentes.
+ </li>
+<li>
+ <a href="#approches">D'autres approches</a>
+ y compris des librairies d'objets fantaisie.
+ </li>
+<li>
+ Utiliser les objets fantaisie avec
+ <a href="#autres_testeurs">d'autres testeurs unitaires</a>.
+ </li>
+</ul>
+<div class="content">
+ <p><a class="target" name="quoi"><h2>Que sont les objets fantaisie ?</h2></a></p>
+ <p>
+ Les objets fantaisie - ou "mock objects" en anglais -
+ ont deux rôles pendant un scénario de test : acteur et critique.
+ </p>
+ <p>
+ Le comportement d'acteur est celui de simuler
+ des objets difficiles à initialiser ou trop consommateurs
+ en temps pendant un test.
+ Le cas classique est celui de la connexion à une base de données.
+ Mettre sur pied une base de données de test au lancement
+ de chaque test ralentirait considérablement les tests
+ et en plus exigerait l'installation d'un moteur
+ de base de données ainsi que des données sur la machine de test.
+ Si nous pouvons simuler la connexion
+ et renvoyer des données à notre guise
+ alors non seulement nous gagnons en pragmatisme
+ sur les tests mais en sus nous pouvons nourrir
+ notre base avec des données falsifiées
+ et voir comment il répond. Nous pouvons
+ simuler une base de données en suspens ou
+ d'autres cas extrêmes sans avoir à créer
+ une véritable panne de base de données.
+ En d'autres termes nous pouvons gagner
+ en contrôle sur l'environnement de test.
+ </p>
+ <p>
+ Si les objets fantaisie ne se comportaient que comme
+ des acteurs alors on les connaîtrait sous le nom de
+ <a href="server_stubs_documentation.html">bouchons serveur</a>.
+ </p>
+ <p>
+ Cependant non seulement les objets fantaisie jouent
+ un rôle (en fournissant à la demande les valeurs requises)
+ mais en plus ils sont aussi sensibles aux messages qui
+ leur sont envoyés (par le biais d'attentes).
+ En posant les paramètres attendus d'une méthode
+ ils agissent comme des gardiens :
+ un appel sur eux doit être réalisé correctement.
+ Si les attentes ne sont pas atteintes ils nous épargnent
+ l'effort de l'écriture d'une assertion de test avec
+ échec en réalisant cette tâche à notre place.
+ Dans le cas d'une connexion à une base de données
+ imaginaire ils peuvent tester si la requête, disons SQL,
+ a bien été formé par l'objet qui utilise cette connexion.
+ Mettez-les sur pied avec des attentes assez précises
+ et vous verrez que vous n'aurez presque plus d'assertion à écrire manuellement.
+ </p>
+
+ <p><a class="target" name="creation"><h2>Créer des objets fantaisie</h2></a></p>
+ <p>
+ Comme pour la création des bouchons serveur, tout ce dont
+ nous avons besoin c'est d'un classe existante.
+ La fameuse connexion à une base de données qui ressemblerait à...
+<pre>
+<strong>class DatabaseConnection {
+ function DatabaseConnection() {
+ }
+
+ function query() {
+ }
+
+ function selectQuery() {
+ }
+}</strong>
+</pre>
+ Cette classe n'a pas encore besoin d'être implémentée.
+ Pour en créer sa version fantaisie nous devons juste
+ inclure la librairie d'objet fantaisie puis lancer le générateur...
+<pre>
+<strong>require_once('simpletest/unit_tester.php');
+require_once('simpletest/mock_objects.php');
+require_once('database_connection.php');
+
+Mock::generate('DatabaseConnection');</strong>
+</pre>
+ Ceci génère une classe clone appelée <span class="new_code">MockDatabaseConnection</span>.
+ Nous pouvons désormais créer des instances de
+ cette nouvelle classe à l'intérieur même de notre scénario de test...
+<pre>
+require_once('simpletest/unit_tester.php');
+require_once('simpletest/mock_objects.php');
+require_once('database_connection.php');
+
+Mock::generate('DatabaseConnection');
+<strong>
+class MyTestCase extends UnitTestCase {
+
+ function testSomething() {
+ $connection = &amp;new MockDatabaseConnection($this);
+ }
+}</strong>
+</pre>
+ Contrairement aux bouchons, le constructeur
+ d'une classe fantaisie a besoin d'une référence au scénario
+ de test pour pouvoir transmettre les succès
+ et les échecs pendant qu'il vérifie les attentes.
+ Concrètement ça veut dire que les objets fantaisie
+ ne peuvent être utilisés qu'au sein d'un scénario de test.
+ Malgré tout, cette puissance supplémentaire implique
+ que les bouchons ne sont que rarement utilisés
+ si des objets fantaisie sont disponibles.
+ </p>
+
+ <p><a class="target" name="bouchon"><h2>Objets fantaisie en action</h2></a></p>
+ <p>
+ La version fantaisie d'une classe contient
+ toutes les méthodes de l'originale.
+ De la sorte une opération comme
+ <span class="new_code">$connection-&gt;query()</span>
+ est encore possible.
+ Tout comme avec les bouchons, nous pouvons remplacer
+ la valeur nulle renvoyée par défaut...
+<pre>
+<strong>$connection-&gt;setReturnValue('query', 37);</strong>
+</pre>
+ Désormais à chaque appel de
+ <span class="new_code">$connection-&gt;query()</span>
+ nous recevons comme résultat 37.
+ Tout comme avec les bouchons nous pouvons utiliser
+ des jokers et surcharger le paramètre joker.
+ Nous pouvons aussi ajouter des méthodes supplémentaires
+ à l'objet fantaisie lors de sa génération
+ et lui choisir un nom de classe qui lui soit propre...
+<pre>
+<strong>Mock::generate('DatabaseConnection', 'MyMockDatabaseConnection', array('setOptions'));</strong>
+</pre>
+ Ici l'objet fantaisie se comportera comme
+ si <span class="new_code">setOptions()</span> existait dans la classe originale.
+ C'est pratique si une classe a utilisé le mécanisme
+ <span class="new_code">overload()</span> de PHP pour ajouter des méthodes dynamiques.
+ Vous pouvez créer des fantaisies spéciales pour simuler cette situation.
+ </p>
+ <p>
+ Tous les modèles disponibles avec les bouchons serveur
+ le sont également avec les objets fantaisie...
+<pre>
+class Iterator {
+ function Iterator() {
+ }
+
+ function next() {
+ }
+}
+</pre>
+ Une nouvelle fois, supposons que cet itérateur
+ ne retourne que du texte jusqu'au moment où il atteint
+ son terme, quand il renvoie <span class="new_code">false</span>.
+ Nous pouvons le simuler avec...
+<pre>
+Mock::generate('Iterator');
+
+class IteratorTest extends UnitTestCase() {
+
+ function testASequence() {<strong>
+ $iterator = &amp;new MockIterator($this);
+ $iterator-&gt;setReturnValue('next', false);
+ $iterator-&gt;setReturnValueAt(0, 'next', 'First string');
+ $iterator-&gt;setReturnValueAt(1, 'next', 'Second string');</strong>
+ ...
+ }
+}
+</pre>
+ Au moment du premier appel à <span class="new_code">next()</span>
+ sur l'itérateur fantaisie il renverra tout d'abord
+ "First string", puis ce sera au tour de
+ "Second string" au deuxième appel
+ et ensuite pour tout appel suivant <span class="new_code">false</span>
+ sera renvoyé.
+ Ces valeurs renvoyées successivement sont prioritaires
+ sur la valeur constante retournée.
+ Cette dernière est un genre de valeur par défaut si vous voulez.
+ </p>
+ <p>
+ Reprenons aussi le conteneur d'information bouchonné
+ avec des pairs clef / valeur...
+<pre>
+class Configuration {
+ function Configuration() {
+ }
+
+ function getValue($key) {
+ }
+}
+</pre>
+ Il s'agit là d'une situation classique
+ d'utilisation d'objets fantaisie étant donné
+ que la configuration peut varier grandement de machine à machine :
+ ça contraint fortement la fiabilité de nos tests
+ si nous l'utilisons directement.
+ Le problème est que toutes les données nous parviennent
+ à travers la méthode <span class="new_code">getValue()</span>
+ et que nous voulons des résultats différents pour des clefs différentes.
+ Heureusement les objets fantaisie ont un système de filtrage...
+<pre>
+<strong>$config = &amp;new MockConfiguration($this);
+$config-&gt;setReturnValue('getValue', 'primary', array('db_host'));
+$config-&gt;setReturnValue('getValue', 'admin', array('db_user'));
+$config-&gt;setReturnValue('getValue', 'secret', array('db_password'));</strong>
+</pre>
+ Le paramètre en plus est une liste d'arguments
+ à faire correspondre. Dans ce cas nous essayons
+ de faire correspondre un unique argument :
+ en l'occurrence la clef recherchée.
+ Maintenant que la méthode <span class="new_code">getValue()</span>
+ est invoquée sur l'objet fantaisie...
+<pre>
+$config-&gt;getValue('db_user')
+</pre>
+ ...elle renverra "admin".
+ Elle le trouve en essayant de faire correspondre
+ les arguments entrants dans sa liste
+ d'arguments sortants les uns après les autres
+ jusqu'au moment où une correspondance exacte est atteinte.
+ </p>
+ <p>
+ Il y a des fois où vous souhaitez
+ qu'un objet spécifique soit servi par la fantaisie
+ plutôt qu'une copie.
+ De nouveau c'est identique au mécanisme des bouchons serveur...
+<pre>
+class Thing {
+}
+
+class Vector {
+ function Vector() {
+ }
+
+ function get($index) {
+ }
+}
+</pre>
+ Dans ce cas vous pouvez placer une référence
+ dans la liste renvoyée par l'objet fantaisie...
+<pre>
+$thing = new Thing();<strong>
+$vector = &amp;new MockVector($this);
+$vector-&gt;setReturnReference('get', $thing, array(12));</strong>
+</pre>
+ Avec cet arrangement vous savez qu'à chaque appel
+ de <span class="new_code">$vector-&gt;get(12)</span>
+ le même <span class="new_code">$thing</span> sera renvoyé.
+ </p>
+
+ <p><a class="target" name="attentes"><h2>Objets fantaisie en critique</h2></a></p>
+ <p>
+ Même si les bouchons serveur vous isolent
+ du désordre du monde réel, il ne s'agit là que
+ de la moitié du bénéfice potentiel.
+ Vous pouvez avoir une classe de test recevant
+ les messages ad hoc, mais est-ce que votre nouvelle classe
+ renvoie bien les bons ?
+ Le tester peut devenir cafouillis sans une librairie d'objets fantaisie.
+ </p>
+ <p>
+ Pour l'exemple, prenons une classe <span class="new_code">SessionPool</span>
+ à laquelle nous allons ajouter une fonction de log.
+ Plutôt que de complexifier la classe originale,
+ nous souhaitons ajouter ce comportement avec un décorateur (GOF).
+ Pour l'instant le code de <span class="new_code">SessionPool</span> ressemble à...
+<pre>
+<strong>class SessionPool {
+ function SessionPool() {
+ ...
+ }
+
+ function &amp;findSession($cookie) {
+ ...
+ }
+ ...
+}
+
+class Session {
+ ...
+}</strong>
+
+</pre>
+ Alors que pour notre code de log, nous avons...
+<pre><strong>
+class Log {
+ function Log() {
+ ...
+ }
+
+ function message() {
+ ...
+ }
+}
+
+class LoggingSessionPool {
+ function LoggingSessionPool(&amp;$session_pool, &amp;$log) {
+ ...
+ }
+
+ function &amp;findSession($cookie) {
+ ...
+ }
+ ...
+}</strong>
+</pre>
+ Dans tout ceci, la seule classe à tester est
+ <span class="new_code">LoggingSessionPool</span>. En particulier,
+ nous voulons vérifier que la méthode <span class="new_code">findSession()</span>
+ est appelée avec le bon identifiant de session au sein du cookie
+ et qu'elle renvoie bien le message "Starting session $cookie"
+ au loggueur.
+ </p>
+ <p>
+ Bien que nous ne testions que quelques lignes
+ de code de production, voici la liste des choses
+ à faire dans un scénario de test conventionnel :
+ <ol>
+ <li>Créer un objet de log.</li>
+ <li>Indiquer le répertoire d'écriture du fichier de log.</li>
+ <li>Modifier les droits sur le répertoire pour pouvoir y écrire le fichier.</li>
+ <li>Créer un objet <span class="new_code">SessionPool</span>.</li>
+ <li>Lancer une session, ce qui demande probablement pas mal de choses.</li>
+ <li>Invoquer <span class="new_code">findSession()</span>.</li>
+ <li>Lire le nouvel identifiant de session (en espérant qu'il existe un accesseur !).</li>
+ <li>Lever une assertion de test pour vérifier que cet identifiant correspond bien au cookie.</li>
+ <li>Lire la dernière ligne du fichier de log.</li>
+ <li>Supprimer avec une (ou plusieurs) expression rationnelle les timestamps de log en trop, etc.</li>
+ <li>Vérifier que le message de session est bien dans le texte.</li>
+ </ol>
+ Pas étonnant que les développeurs détestent
+ écrire des tests quand ils sont aussi ingrats.
+ Pour rendre les choses encore pire, à chaque fois que
+ le format de log change ou bien que la méthode de création
+ des sessions change, nous devons réécrire une partie
+ des tests alors même qu'ils ne testent pas ces parties
+ du système. Nous sommes en train de préparer
+ le cauchemar pour les développeurs de ces autres classes.
+ </p>
+ <p>
+ A la place, voici la méthode complète pour le test
+ avec un peu de magie via les objets fantaisie...
+<pre>
+Mock::generate('Session');
+Mock::generate('SessionPool');
+Mock::generate('Log');
+
+class LoggingSessionPoolTest extends UnitTestCase {
+ ...
+ function testFindSessionLogging() {<strong>
+ $session = &amp;new MockSession($this);
+ $pool = &amp;new MockSessionPool($this);
+ $pool-&gt;setReturnReference('findSession', $session);
+ $pool-&gt;expectOnce('findSession', array('abc'));
+
+ $log = &amp;new MockLog($this);
+ $log-&gt;expectOnce('message', array('Starting session abc'));
+
+ $logging_pool = &amp;new LoggingSessionPool($pool, $log);
+ $this-&gt;assertReference($logging_pool-&gt;findSession('abc'), $session);
+ $pool-&gt;tally();
+ $log-&gt;tally();</strong>
+ }
+}
+</pre>
+ Commençons par écrire une session simulacre.
+ Pas la peine d'être trop pointilleux avec
+ celle-ci puisque la vérification de la session
+ désirée est effectuée ailleurs. Nous avons
+ juste besoin de vérifier qu'il s'agit de
+ la même que celle qui vient du groupe commun des sessions.
+ </p>
+ <p>
+ <span class="new_code">findSession()</span> est un méthode fabrique
+ dont la simulation est décrite <a href="#stub">plus haut</a>.
+ Le point de départ vient avec le premier appel
+ <span class="new_code">expectOnce()</span>. Cette ligne indique
+ qu'à chaque fois que <span class="new_code">findSession()</span>
+ est invoqué sur l'objet fantaisie, il vérifiera
+ les arguments entrant. S'il ne reçoit
+ que la chaîne "abc" en tant qu'argument
+ alors un succès est envoyé au testeur unitaire,
+ sinon c'est un échec qui est généré.
+ Il s'agit là de la partie qui teste si nous avons bien
+ la bonne session. La liste des arguments suit
+ une format identique à celui qui précise les valeurs renvoyées.
+ Vous pouvez avoir des jokers et des séquences
+ et l'ordre de l'évaluation restera le même.
+ </p>
+ <p>
+ Si l'appel n'est jamais effectué alors n'est généré
+ ni le succès, ni l'échec. Pour contourner cette limitation,
+ nous devons dire à l'objet fantaisie que le test est terminé :
+ il pourra alors décider si les attentes ont été répondues.
+ L'assertion du testeur unitaire de ceci est déclenchée
+ par l'appel <span class="new_code">tally()</span> à la fin du test.
+ </p>
+ <p>
+ Nous utilisons le même modèle pour mettre sur pied
+ le loggueur fantaisie. Nous lui indiquons que <span class="new_code">message()</span>
+ devrait être invoqué une fois et une fois seulement
+ avec l'argument "Starting session abc".
+ En testant les arguments d'appel, plutôt que ceux de sortie du loggueur,
+ nous isolons le test de tout modification dans le loggueur.
+ </p>
+ <p>
+ Nous commençons le lancement nos tests à la création
+ du nouveau <span class="new_code">LoggingSessionPool</span>
+ et nous l'alimentons avec nos objets fantaisie juste créés.
+ Désormais tout est sous contrôle. Au final nous confirmons
+ que le <span class="new_code">$session</span> donné au décorateur est bien
+ celui reçu et prions les objets fantaisie de lancer leurs
+ tests de comptage d'appel interne avec les appels <span class="new_code">tally()</span>.
+ </p>
+ <p>
+ Il y a encore pas mal de code de test, mais ce code est très strict.
+ S'il vous semble encore terrifiant il l'est bien moins
+ que si nous avions essayé sans les objets fantaisie
+ et ce test en particulier, interactions plutôt que résultat,
+ est toujours plus difficile à mettre en place.
+ Le plus souvent vous aurez besoin de tester des situations
+ plus complexes sans ce niveau ni cette précision.
+ En outre une partie peut être remaniée avec la méthode
+ de scénario de test <span class="new_code">setUp()</span>.
+ </p>
+ <p>
+ Voici la liste complète des attentes que vous pouvez
+ placer sur un objet fantaisie avec
+ <a href="http://www.lastcraft.com/simple_test.php">SimpleTest</a>...
+ <table>
+<thead>
+ <tr>
+<th>Attente</th>
+<th>Nécessite <span class="new_code">tally()</span>
+</th>
+</tr>
+ </thead>
+<tbody>
+<tr>
+ <td><span class="new_code">expectArguments($method, $args)</span></td>
+ <td style="text-align: center">Non</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectArgumentsAt($timing, $method, $args)</span></td>
+ <td style="text-align: center">Non</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectCallCount($method, $count)</span></td>
+ <td style="text-align: center">Oui</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectMaximumCallCount($method, $count)</span></td>
+ <td style="text-align: center">Non</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectMinimumCallCount($method, $count)</span></td>
+ <td style="text-align: center">Oui</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectNever($method)</span></td>
+ <td style="text-align: center">Non</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectOnce($method, $args)</span></td>
+ <td style="text-align: center">Oui</td>
+ </tr>
+ <tr>
+ <td><span class="new_code">expectAtLeastOnce($method, $args)</span></td>
+ <td style="text-align: center">Oui</td>
+ </tr>
+ </tbody>
+</table>
+ Où les paramètres sont...
+ <dl>
+ <dt class="new_code">$method</dt>
+ <dd>Le nom de la méthode, sous la forme d'une chaîne,
+ à laquelle la condition doit être appliquée.</dd>
+ <dt class="new_code">$args</dt>
+ <dd>
+ Les arguments sous la forme d'une liste.
+ Les jokers peuvent être inclus de la même manière
+ qu'avec <span class="new_code">setReturn()</span>.
+ Cet argument est optionnel pour <span class="new_code">expectOnce()</span>
+ et <span class="new_code">expectAtLeastOnce()</span>.
+ </dd>
+ <dt class="new_code">$timing</dt>
+ <dd>
+ Le seul point dans le temps pour tester
+ la condition. Le premier appel commence à zéro.
+ </dd>
+ <dt class="new_code">$count</dt>
+ <dd>Le nombre d'appels attendu.</dd>
+ </dl>
+ La méthode <span class="new_code">expectMaximumCallCount()</span>
+ est légèrement différente dans le sens où elle ne pourra
+ générer qu'un échec. Elle reste silencieuse
+ si la limite n'est jamais atteinte.
+ </p>
+ <p>
+ Par ailleurs si vous avez just un appel dans votre test,
+ vérifiez bien que vous utiliser
+ <span class="new_code">expectOnce</span>.<br>
+ Utiliser <span class="new_code">$mocked-&gt;expectAt(0, 'method', 'args);</span>
+ tout seul ne sera pas pris en compte :
+ la vérification des arguments et le comptage total
+ sont pour l'instant encore indépendant.
+ </p>
+ <p>
+ Comme avec les assertions dans les scénarios de test,
+ toutes ces attentes peuvent accepter une surcharge de
+ message sous la forme d'un paramètre supplémentaire.
+ Par ailleurs le message d'échec original peut être inclus
+ dans le résultat avec "%s".
+ </p>
+
+ <p><a class="target" name="approches"><h2>D'autres approches</h2></a></p>
+ <p>
+ Il existe trois approches pour créer des objets
+ fantaisie en comprenant celle utilisée par SimpleTest.
+ Les coder à la main en utilisant une classe de base,
+ les générer dans un fichier ou les générer dynamiquement à la volée.
+ </p>
+ <p>
+ Les objets fantaisie générés avec
+ <a href="simple_test.html">SimpleTest</a> sont dynamiques.
+ Ils sont créés à l'exécution dans la mémoire,
+ grâce à <span class="new_code">eval()</span>, plutôt qu'écrits dans un fichier.
+ Cette opération les rend facile à créer,
+ en une seule ligne, surtout par rapport à leur création
+ à la main dans une hiérarchie de classe parallèle.
+ Le problème avec ce comportement tient généralement
+ dans la mise en place des tests proprement dits.
+ Si les objets originaux changent les versions fantaisie
+ sur lesquels reposent les tests, une désynchronisation peut subvenir.
+ Cela peut aussi arriver avec l'approche en hiérarchie parallèle,
+ mais c'est détecté beaucoup plus vite.
+ </p>
+ <p>
+ Bien sûr, la solution est d'ajouter de véritables tests d'intégration.
+ Vous n'en avez pas besoin de beaucoup
+ et le côté pratique des objets fantaisie fait plus
+ que compenser la petite dose de test supplémentaire.
+ Vous ne pouvez pas avoir confiance dans du code qui
+ ne serait testé que par des objets fantaisie.
+ </p>
+ <p>
+ Si vous restez déterminé de construire des librairies
+ statiques d'objets fantaisie parce que vous souhaitez
+ émuler un comportement très spécifique,
+ vous pouvez y parvenir grâce au générateur de classe de SimpleTest.
+ Dans votre fichier librairie, par exemple
+ <em>mocks/connection.php</em> pour une connexion à une base de données,
+ créer un objet fantaisie et provoquer l'héritage
+ pour hériter pour surcharger des méthodes spéciales
+ ou ajouter des préréglages...
+<pre>
+&lt;?php
+ require_once('simpletest/mock_objects.php');
+ require_once('../classes/connection.php');
+<strong>
+ Mock::generate('Connection', 'BasicMockConnection');
+ class MockConnection extends BasicMockConnection {
+ function MockConnection(&amp;$test, $wildcard = '*') {
+ $this-&gt;BasicMockConnection($test, $wildcard);
+ $this-&gt;setReturn('query', false);
+ }
+ }</strong>
+?&gt;
+</pre>
+ L'appel <span class="new_code">generate</span> dit au générateur de classe
+ d'en créer une appelée <span class="new_code">BasicMockConnection</span>
+ plutôt que la plus courante <span class="new_code">MockConnection</span>.
+ Ensuite nous héritons à partir de celle-ci pour obtenir
+ notre version de <span class="new_code">MockConnection</span>.
+ En interceptant de cette manière nous pouvons ajouter
+ un comportement, ici transformer la valeur par défaut de
+ <span class="new_code">query()</span> en "false".
+ En utilisant le nom par défaut nous garantissons
+ que le générateur de classe fantaisie n'en recréera
+ pas une autre différente si il est invoqué ailleurs
+ dans les tests. Il ne créera jamais de classe
+ si elle existe déjà. Aussi longtemps que le fichier
+ ci-dessus est inclus avant alors tous les tests qui
+ généraient <span class="new_code">MockConnection</span> devraient
+ utiliser notre version à présent. Par contre si
+ nous avons une erreur dans l'ordre et que la librairie
+ de fantaisie en crée une d'abord alors la création
+ de la classe échouera tout simplement.
+ </p>
+ <p>
+ Utiliser cette astuce si vous vous trouvez avec beaucoup
+ de comportement en commun sur les objets fantaisie
+ ou si vous avez de fréquents problèmes d'intégration
+ plus tard dans les étapes de test.
+ </p>
+
+ <p><a class="target" name="autres_testeurs"><h2>Je pense que SimpleTest pue !</h2></a></p>
+ <p>
+ Mais au moment d'écrire ces lignes c'est le seul
+ à gérer les objets fantaisie, donc vous êtes bloqué avec lui ?
+ </p>
+ <p>
+ Non, pas du tout.
+ <a href="simple_test.html">SimpleTest</a> est une boîte à outils
+ et parmi ceux-ci on trouve les objets fantaisie
+ qui peuvent être utilisés indépendamment.
+ Supposons que vous avez votre propre testeur unitaire favori
+ et que tous vos tests actuels l'utilisent.
+ Prétendez que vous avez appelé votre tester unitaire PHPUnit
+ (c'est ce que tout le monde a fait) et que la classe principale
+ de test ressemble à...
+<pre>
+class PHPUnit {
+ function PHPUnit() {
+ }
+
+ function assertion($message, $assertion) {
+ }
+ ...
+}
+</pre>
+ La seule chose que la méthode <span class="new_code">assertion()</span> réalise,
+ c'est de préparer une sortie embellie alors le paramètre boolien
+ de l'assertion sert à déterminer s'il s'agit d'une erreur ou d'un succès.
+ Supposons qu'elle est utilisée de la manière suivante...
+<pre>
+$unit_test = new PHPUnit();
+$unit_test&gt;assertion('I hope this file exists', file_exists('my_file'));
+</pre>
+ Comment utiliser les objets fantaisie avec ceci ?
+ </p>
+ <p>
+ Il y a une méthode protégée sur la classe de base
+ des objets fantaisie : elle s'appelle <span class="new_code">_assertTrue()</span>.
+ En surchargeant cette méthode nous pouvons utiliser
+ notre propre format d'assertion.
+ Nous commençons avec une sous-classe, dans <em>my_mock.php</em>...
+<pre>
+<strong>&lt;?php
+ require_once('simpletest/mock_objects.php');
+
+ class MyMock extends SimpleMock() {
+ function MyMock(&amp;$test, $wildcard) {
+ $this-&gt;SimpleMock($test, $wildcard);
+ }
+
+ function _assertTrue($assertion, $message) {
+ $test = &amp;$this-&gt;getTest();
+ $test-&gt;assertion($message, $assertion);
+ }
+ }
+?&gt;</strong>
+</pre>
+ Maintenant une instance de <span class="new_code">MyMock</span>
+ créera un objet qui parle le même langage que votre testeur.
+ Bien sûr le truc c'est que nous créons jamais un tel objet :
+ le générateur s'en chargera. Nous avons juste besoin
+ d'une ligne de code supplémentaire pour dire au générateur
+ d'utiliser vos nouveaux objets fantaisie...
+<pre>
+&lt;?php
+ require_once('simpletst/mock_objects.php');
+
+ class MyMock extends SimpleMock() {
+ function MyMock($test, $wildcard) {
+ $this-&gt;SimpleMock(&amp;$test, $wildcard);
+ }
+
+ function _assertTrue($assertion, $message , &amp;$test) {
+ $test-&gt;assertion($message, $assertion);
+ }
+ }<strong>
+ SimpleTestOptions::setMockBaseClass('MyMock');</strong>
+?&gt;
+</pre>
+ A partir de maintenant vous avez juste à inclure
+ <em>my_mock.php</em> à la place de la version par défaut
+ <em>simple_mock.php</em> et vous pouvez introduire
+ des objets fantaisie dans votre suite de tests existants.
+ </p>
+
+ </div>
+ References and related information...
+ <ul>
+<li>
+ L'article originel sur
+ <a href="http://www.mockobjects.com/">les objets fantaisie</a>.
+ </li>
+<li>
+ La page du projet SimpleTest sur
+ <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
+ </li>
+<li>
+ La page d'accueil de SimpleTest sur
+ <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
+ </li>
+</ul>
+<div class="menu_back"><div class="menu">
+<a href="index.html">SimpleTest</a>
+ |
+ <a href="overview.html">Overview</a>
+ |
+ <a href="unit_test_documentation.html">Unit tester</a>
+ |
+ <a href="group_test_documentation.html">Group tests</a>
+ |
+ <a href="mock_objects_documentation.html">Mock objects</a>
+ |
+ <a href="partial_mocks_documentation.html">Partial mocks</a>
+ |
+ <a href="reporter_documentation.html">Reporting</a>
+ |
+ <a href="expectation_documentation.html">Expectations</a>
+ |
+ <a href="web_tester_documentation.html">Web tester</a>
+ |
+ <a href="form_testing_documentation.html">Testing forms</a>
+ |
+ <a href="authentication_documentation.html">Authentication</a>
+ |
+ <a href="browser_documentation.html">Scriptable browser</a>
+</div></div>
+<div class="copyright">
+ Copyright<br>Marcus Baker 2006
+ </div>
+</body>
+</html>