summaryrefslogtreecommitdiff
path: root/tests/test_tools/simpletest/docs/fr/mock_objects_documentation.html
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_tools/simpletest/docs/fr/mock_objects_documentation.html')
-rwxr-xr-xtests/test_tools/simpletest/docs/fr/mock_objects_documentation.html492
1 files changed, 0 insertions, 492 deletions
diff --git a/tests/test_tools/simpletest/docs/fr/mock_objects_documentation.html b/tests/test_tools/simpletest/docs/fr/mock_objects_documentation.html
deleted file mode 100755
index 0ce48bc9..00000000
--- a/tests/test_tools/simpletest/docs/fr/mock_objects_documentation.html
+++ /dev/null
@@ -1,492 +0,0 @@
-<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">
-<h2>
-<a href="index.html">SimpleTest</a>
-</h2>
-<ul>
-<li>
-<a href="overview.html">Overview</a>
-</li>
-<li>
-<a href="unit_test_documentation.html">Unit tester</a>
-</li>
-<li>
-<a href="group_test_documentation.html">Group tests</a>
-</li>
-<li>
-<a href="server_stubs_documentation.html">Server stubs</a>
-</li>
-<li>
-<a href="mock_objects_documentation.html">Mock objects</a>
-</li>
-<li>
-<a href="partial_mocks_documentation.html">Partial mocks</a>
-</li>
-<li>
-<a href="reporter_documentation.html">Reporting</a>
-</li>
-<li>
-<a href="expectation_documentation.html">Expectations</a>
-</li>
-<li>
-<a href="web_tester_documentation.html">Web tester</a>
-</li>
-<li>
-<a href="form_testing_documentation.html">Testing forms</a>
-</li>
-<li>
-<a href="authentication_documentation.html">Authentication</a>
-</li>
-<li>
-<a href="browser_documentation.html">Scriptable browser</a>
-</li>
-</ul>
-</div>
-</div>
-<h1>Documentation sur les objets fantaisie</h1>
-<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&ocirc;les pendant un sc&eacute;nario de test : acteur et critique.
- </p>
- <p>
- Le comportement d'acteur est celui de simuler des objets difficiles &agrave; initialiser ou trop consommateurs en temps pendant un test. Le cas classique est celui de la connexion &agrave; une base de donn&eacute;es. Mettre sur pied une base de donn&eacute;es de test au lancement de chaque test ralentirait consid&eacute;rablement les tests et en plus exigerait l'installation d'un moteur de base de donn&eacute;es ainsi que des donn&eacute;es sur la machine de test. Si nous pouvons simuler la connexion et renvoyer des donn&eacute;es &agrave; notre guise alors non seulement nous gagnons en pragmatisme sur les tests mais en sus nous pouvons nourrir notre base avec des donn&eacute;es falsifi&eacute;es et voir comment il r&eacute;pond. Nous pouvons simuler une base de donn&eacute;es en suspens ou d'autres cas extr&ecirc;mes sans avoir &agrave; cr&eacute;er une v&eacute;ritable panne de base de donn&eacute;es. En d'autres termes nous pouvons gagner en contr&ocirc;le sur l'environnement de test.
- </p>
- <p>
- Si les objets fantaisie ne se comportaient que comme des acteurs alors on les conna&icirc;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&ocirc;le (en fournissant &agrave; la demande les valeurs requises) mais en plus ils sont aussi sensibles aux messages qui leur sont envoy&eacute;s (par le biais d'attentes). En posant les param&egrave;tres attendus d'une m&eacute;thode ils agissent comme des gardiens : un appel sur eux doit &ecirc;tre r&eacute;alis&eacute; correctement. Si les attentes ne sont pas atteintes ils nous &eacute;pargnent l'effort de l'&eacute;criture d'une assertion de test avec &eacute;chec en r&eacute;alisant cette t&acirc;che &agrave; notre place. Dans le cas d'une connexion &agrave; une base de donn&eacute;es imaginaire ils peuvent tester si la requ&ecirc;te, disons SQL, a bien &eacute;t&eacute; form&eacute; par l'objet qui utilise cette connexion. Mettez-les sur pied avec des attentes assez pr&eacute;cises et vous verrez que vous n'aurez presque plus d'assertion &agrave; &eacute;crire manuellement.
- </p>
-
- <p>
-<a class="target" name="creation">
-<h2>Cr&eacute;er des objets fantaisie</h2>
-</a>
-</p>
- <p>
- Comme pour la cr&eacute;ation des bouchons serveur, tout ce dont nous avons besoin c'est d'un classe existante. La fameuse connexion &agrave; une base de donn&eacute;es qui ressemblerait &agrave;...
-<pre>
-<strong>class DatabaseConnection {
- function DatabaseConnection() {
- }
-
- function query() {
- }
-
- function selectQuery() {
- }
-}</strong>
-</pre>
- Cette classe n'a pas encore besoin d'&ecirc;tre impl&eacute;ment&eacute;e. Pour en cr&eacute;er sa version fantaisie nous devons juste inclure la librairie d'objet fantaisie puis lancer le g&eacute;n&eacute;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&eacute;n&egrave;re une classe clone appel&eacute;e <span class="new_code">MockDatabaseConnection</span>. Nous pouvons d&eacute;sormais cr&eacute;er des instances de cette nouvelle classe &agrave; l'int&eacute;rieur m&ecirc;me de notre sc&eacute;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&eacute;f&eacute;rence au sc&eacute;nario de test pour pouvoir transmettre les succ&egrave;s et les &eacute;checs pendant qu'il v&eacute;rifie les attentes. Concr&egrave;tement &ccedil;a veut dire que les objets fantaisie ne peuvent &ecirc;tre utilis&eacute;s qu'au sein d'un sc&eacute;nario de test. Malgr&eacute; tout, cette puissance suppl&eacute;mentaire implique que les bouchons ne sont que rarement utilis&eacute;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&eacute;thodes de l'originale. De la sorte une op&eacute;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&eacute;e par d&eacute;faut...
-<pre>
-<strong>$connection-&gt;setReturnValue('query', 37);</strong>
-</pre>
- D&eacute;sormais &agrave; chaque appel de <span class="new_code">$connection-&gt;query()</span> nous recevons comme r&eacute;sultat 37. Tout comme avec les bouchons nous pouvons utiliser des jokers et surcharger le param&egrave;tre joker. Nous pouvons aussi ajouter des m&eacute;thodes suppl&eacute;mentaires &agrave; l'objet fantaisie lors de sa g&eacute;n&eacute;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&eacute; le m&eacute;canisme <span class="new_code">overload()</span> de PHP pour ajouter des m&eacute;thodes dynamiques. Vous pouvez cr&eacute;er des fantaisies sp&eacute;ciales pour simuler cette situation.
- </p>
- <p>
- Tous les mod&egrave;les disponibles avec les bouchons serveur le sont &eacute;galement avec les objets fantaisie...
-<pre>
-class Iterator {
- function Iterator() {
- }
-
- function next() {
- }
-}
-</pre>
- Une nouvelle fois, supposons que cet it&eacute;rateur ne retourne que du texte jusqu'au moment o&ugrave; 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 &agrave; <span class="new_code">next()</span> sur l'it&eacute;rateur fantaisie il renverra tout d'abord "First string", puis ce sera au tour de "Second string" au deuxi&egrave;me appel et ensuite pour tout appel suivant <span class="new_code">false</span> sera renvoy&eacute;. Ces valeurs renvoy&eacute;es successivement sont prioritaires sur la valeur constante retourn&eacute;e. Cette derni&egrave;re est un genre de valeur par d&eacute;faut si vous voulez.
- </p>
- <p>
- Reprenons aussi le conteneur d'information bouchonn&eacute; avec des pairs clef / valeur...
-<pre>
-class Configuration {
- function Configuration() {
- }
-
- function getValue($key) {
- }
-}
-</pre>
- Il s'agit l&agrave; d'une situation classique d'utilisation d'objets fantaisie &eacute;tant donn&eacute; que la configuration peut varier grandement de machine &agrave; machine : &ccedil;a contraint fortement la fiabilit&eacute; de nos tests si nous l'utilisons directement. Le probl&egrave;me est que toutes les donn&eacute;es nous parviennent &agrave; travers la m&eacute;thode <span class="new_code">getValue()</span> et que nous voulons des r&eacute;sultats diff&eacute;rents pour des clefs diff&eacute;rentes. Heureusement les objets fantaisie ont un syst&egrave;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&egrave;tre en plus est une liste d'arguments &agrave; faire correspondre. Dans ce cas nous essayons de faire correspondre un unique argument : en l'occurrence la clef recherch&eacute;e. Maintenant que la m&eacute;thode <span class="new_code">getValue()</span> est invoqu&eacute;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&egrave;s les autres jusqu'au moment o&ugrave; une correspondance exacte est atteinte.
- </p>
- <p>
- Il y a des fois o&ugrave; vous souhaitez qu'un objet sp&eacute;cifique soit servi par la fantaisie plut&ocirc;t qu'une copie. De nouveau c'est identique au m&eacute;canisme des bouchons serveur...
-<pre>
-class Thing {
-}
-
-class Vector {
- function Vector() {
- }
-
- function get($index) {
- }
-}
-</pre>
- Dans ce cas vous pouvez placer une r&eacute;f&eacute;rence dans la liste renvoy&eacute;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'&agrave; chaque appel de <span class="new_code">$vector-&gt;get(12)</span> le m&ecirc;me <span class="new_code">$thing</span> sera renvoy&eacute;.
- </p>
-
- <p>
-<a class="target" name="attentes">
-<h2>Objets fantaisie en critique</h2>
-</a>
-</p>
- <p>
- M&ecirc;me si les bouchons serveur vous isolent du d&eacute;sordre du monde r&eacute;el, il ne s'agit l&agrave; que de la moiti&eacute; du b&eacute;n&eacute;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> &agrave; laquelle nous allons ajouter une fonction de log. Plut&ocirc;t que de complexifier la classe originale, nous souhaitons ajouter ce comportement avec un d&eacute;corateur (GOF). Pour l'instant le code de <span class="new_code">SessionPool</span> ressemble &agrave;...
-<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 &agrave; tester est <span class="new_code">LoggingSessionPool</span>. En particulier, nous voulons v&eacute;rifier que la m&eacute;thode <span class="new_code">findSession()</span> est appel&eacute;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 &agrave; faire dans un sc&eacute;nario de test conventionnel :
- <ol>
- <li>Cr&eacute;er un objet de log.</li>
- <li>Indiquer le r&eacute;pertoire d'&eacute;criture du fichier de log.</li>
- <li>Modifier les droits sur le r&eacute;pertoire pour pouvoir y &eacute;crire le fichier.</li>
- <li>Cr&eacute;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 sessions (en esp&eacute;rant qu'il existe un accesseur !).</li>
- <li>Lever une assertion de test pour v&eacute;rifier que cet identifiant correspond bien au cookie.</li>
- <li>Lire la derni&egrave;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&eacute;rifier que le message de session est bien dans le texte.</li>
- </ol>
- Pas &eacute;tonnant que les d&eacute;veloppeurs d&eacute;testent &eacute;crire des tests quand ils sont aussi ingrats. Pour rendre les choses encore pire, &agrave; chaque fois que le format de log change ou bien que la m&eacute;thode de cr&eacute;ation des sessions change, nous devons r&eacute;&eacute;crire une partie des tests alors m&ecirc;me qu'ils ne testent pas ces parties du syst&egrave;me. Nous sommes en train de pr&eacute;parer le cauchemar pour les d&eacute;veloppeurs de ces autres classes.
- </p>
- <p>
- A la place, voici la m&eacute;thode compl&egrave;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&ccedil;ons par &eacute;crire une session simulacre. Pas la peine d'&ecirc;tre trop pointilleux avec celle-ci puisque la v&eacute;rification de la session d&eacute;sir&eacute;e est effectu&eacute;e ailleurs. Nous avons juste besoin de v&eacute;rifier qu'il s'agit de la m&ecirc;me que celle qui vient du groupe commun des sessions.
- </p>
- <p>
- <span class="new_code">findSession()</span> est un m&eacute;thode fabrique dont la simulation est d&eacute;crite <a href="#stub">plus haut</a>. Le point de d&eacute;part vient avec le premier appel <span class="new_code">expectOnce()</span>. Cette ligne indique qu'&agrave; chaque fois que <span class="new_code">findSession()</span> est invoqu&eacute; sur l'objet fantaisie, il v&eacute;rifiera les arguments entrant. S'il ne re&ccedil;oit que la cha&icirc;ne "abc" en tant qu'argument alors un succ&egrave;s est envoy&eacute; au testeur unitaire, sinon c'est un &eacute;chec qui est g&eacute;n&eacute;r&eacute;. Il s'agit l&agrave; de la partie qui teste si nous avons bien la bonne session. La liste des arguments suit une format identique &agrave; celui qui pr&eacute;cise les valeurs renvoy&eacute;es. Vous pouvez avoir des jokers et des s&eacute;quences et l'ordre de l'&eacute;valuation restera le m&ecirc;me.
- </p>
- <p>
- Si l'appel n'est jamais effectu&eacute; alors n'est g&eacute;n&eacute;r&eacute; ni le succ&egrave;s, ni l'&eacute;chec. Pour contourner cette limitation, nous devons dire &agrave; l'objet fantaisie que le test est termin&eacute; : il pourra alors d&eacute;cider si les attentes ont &eacute;t&eacute; r&eacute;pondues. L'assertion du testeur unitaire de ceci est d&eacute;clench&eacute;e par l'appel <span class="new_code">tally()</span> &agrave; la fin du test.
- </p>
- <p>
- Nous utilisons le m&ecirc;me mod&egrave;le pour mettre sur pied le loggueur fantaisie. Nous lui indiquons que <span class="new_code">message()</span> devrait &ecirc;tre invoqu&eacute; une fois et une fois seulement avec l'argument "Starting session abc". En testant les arguments d'appel, plut&ocirc;t que ceux de sorite du loggueur, nous isolons le test de tout modification dans le loggueur.
- </p>
- <p>
- Nous commen&ccedil;ons le lancement nos tests &agrave; la cr&eacute;ation du nouveau <span class="new_code">LoggingSessionPool</span> et nous l'alimentons avec nos objets fantaisie juste cr&eacute;&eacute;s. D&eacute;sormais tout est sous contr&ocirc;le. Au final nous confirmons que le <span class="new_code">$session</span> donn&eacute; au d&eacute;corateur est bien celui re&ccedil;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&egrave;s strict. S'il vous semble encore terrifiant il l'est bien moins que si nous avions essay&eacute; sans les objets fantaisie et ce test en particulier, interactions plut&ocirc;t que r&eacute;sultat, est toujours plus difficile &agrave; mettre en place. Le plus souvent vous aurez besoin de tester des situations plus complexes sans ce niveau ni cette pr&eacute;cision. En outre une partie peut &ecirc;tre remani&eacute;e avec la m&eacute;thode de sc&eacute;nario de test <span class="new_code">setUp()</span>.
- </p>
- <p>
- Voici la liste compl&egrave;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&eacute;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&ugrave; les param&egrave;tres sont...
- <dl>
- <dt class="new_code">$method</dt>
- <dd>Le nom de la m&eacute;thode, sous la forme d'une cha&icirc;ne, &agrave; laquelle la condition doit &ecirc;tre appliqu&eacute;e.</dd>
- <dt class="new_code">$args</dt>
- <dd>
- Les arguments sous la forme d'une liste. Les jokers peuvent &ecirc;tre inclus de la m&ecirc;me mani&egrave;re qu'avec <span class="new_code">setReturn()</span>. Cet argument est optionel 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 &agrave; z&eacute;ro.
- </dd>
- <dt class="new_code">$count</dt>
- <dd>Le nombre d'appels attendu.</dd>
- </dl>
- La m&eacute;thode <span class="new_code">expectMaximumCallCount()</span> est l&eacute;g&egrave;rement diff&eacute;rente dans le sens o&ugrave; elle ne pourra g&eacute;n&eacute;rer qu'un &eacute;chec. Elle reste silencieuse si la limite n'est jamais atteinte.
- </p>
- <p>
- Comme avec les assertions dans les sc&eacute;narios de test, toutes ces attentes peuvent accepter une surcharge de message sous la forme d'un param&egrave;tre suppl&eacute;mentaire. Par ailleurs le message d'&eacute;chec original peut &ecirc;tre inclus dans le r&eacute;sultat avec "%s".
- </p>
-
- <p>
-<a class="target" name="approches">
-<h2>D'autres approches</h2>
-</a>
-</p>
- <p>
- Il existe trois approches pour cr&eacute;er des objets fantaisie en comprenant celle utiliser par SimpleTest. Les coder &agrave; la main en utilisant une classe de base, les g&eacute;n&eacute;rer dans un fichier ou les g&eacute;n&eacute;rer dynamiquement &agrave; la vol&eacute;e.
- </p>
- <p>
- Les objets fantaisie g&eacute;n&eacute;r&eacute;s avec <a href="simple_test.html">SimpleTest</a> sont dynamiques. Ils sont cr&eacute;&eacute;s &agrave; l'ex&eacute;cution dans la m&eacute;moire, gr&acirc;ce &agrave; <span class="new_code">eval()</span>, plut&ocirc;t qu'&eacute;crit dans un fichier. Cette op&eacute;ration les rend facile &agrave; cr&eacute;er, en une seule ligne, surtout par rapport &agrave; leur cr&eacute;ation &agrave; la main dans une hi&eacute;rarchie de classe parall&egrave;le. Le probl&egrave;me avec ce comportement tient g&eacute;n&eacute;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&eacute;synchronisation peut subvenir. Cela peut aussi arriver avec l'approche en hi&eacute;rarchie parall&egrave;le, mais c'est d&eacute;tect&eacute; beaucoup plus vite.
- </p>
- <p>
- Bien s&ucirc;r, la solution est d'ajouter de v&eacute;ritables tests d'int&eacute;gration. Vous n'en avez pas besoin de beaucoup et le c&ocirc;t&eacute; pratique des objets fantaisie fait plus que compenser la petite dose de test suppl&eacute;mentaire. Vous ne pouvez pas avoir confiance dans du code qui ne serait test&eacute; que par des objets fantaisie.
- </p>
- <p>
- Si vous restez d&eacute;termin&eacute; de construire des librairies statiques d'objets fantaisie parce que vous souhaitez &eacute;muler un comportement tr&egrave;s sp&eacute;cifique, vous pouvez y parvenir gr&acirc;ce au g&eacute;n&eacute;rateur de classe de SimpleTest. Dans votre fichier librairie, par exemple <em>mocks/connection.php</em> pour une connexion &agrave; une base de donn&eacute;es, cr&eacute;er un objet fantaisie et provoquer m'h&eacute;ritage pour h&eacute;riter pour surcharger des m&eacute;thodes sp&eacute;ciales ou ajouter des pr&eacute;r&eacute;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&eacute;n&eacute;rateur de classe d'en cr&eacute;er une appel&eacute;e <span class="new_code">BasicMockConnection</span> plut&ocirc;t que la plus courante <span class="new_code">MockConnection</span>. Ensuite nous h&eacute;ritons &agrave; partir de celle-ci pour obtenir notre version de <span class="new_code">MockConnection</span>. En interceptant de cette mani&egrave;re nous pouvons ajouter un comportement, ici transformer la valeur par d&eacute;faut de <span class="new_code">query()</span> en "false".
- En utilisant le nom par d&eacute;faut nous garantissons que le g&eacute;n&eacute;rateur de classe fantaisie n'en recr&eacute;era pas une autre diff&eacute;rente si il est invoqu&eacute; ailleurs dans les tests. Il ne cr&eacute;era jamais de classe si elle existe d&eacute;j&agrave;. Aussi longtemps que le fichier ci-dessus est inclus avant alors tous les tests qui g&eacute;n&eacute;raient <span class="new_code">MockConnection</span> devraient utiliser notre version &agrave; pr&eacute;sent. Par contre si nous avons une erreur dans l'ordre et que la librairie de fantaisie en cr&eacute;e une d'abord alors la cr&eacute;ation de la classe &eacute;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&eacute;quents probl&egrave;mes d'int&eacute;gration plus tard dans les &eacute;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'&eacute;crire ces lignes c'est le seul &agrave; g&eacute;rer les objets fantaisie, donc vous &ecirc;tes bloqu&eacute; avec lui ?
- </p>
- <p>
- Non, pas du tout.
- <a href="simple_test.html">SimpleTest</a> est une bo&icirc;te &agrave; outils et parmi ceux-ci on trouve les objets fantaisie qui peuvent &ecirc;tre utilis&eacute;s ind&eacute;pendamment. Supposons que vous avez votre propre testeur unitaire favori et que tous vos tests actuels l'utilisent. Pr&eacute;tendez que vous avez appel&eacute; votre tester unitaire PHPUnit (c'est ce que tout le monde a fait) et que la classe principale de test ressemble &agrave;...
-<pre>
-class PHPUnit {
- function PHPUnit() {
- }
-
- function assertion($message, $assertion) {
- }
- ...
-}
-</pre>
- La seule chose que la m&eacute;thode <span class="new_code">assertion()</span> r&eacute;alise, c'est de pr&eacute;parer une sortie embellie alors le param&egrave;tre boolien de l'assertion sert &agrave; d&eacute;terminer s'il s'agit d'une erreur ou d'un succ&egrave;s. Supposons qu'elle est utilis&eacute;e de la mani&egrave;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&eacute;thode prot&eacute;g&eacute;e sur la classe de base des objets fantaisie : elle s'appelle <span class="new_code">_assertTrue()</span>. En surchargeant cette m&eacute;thode nous pouvons utiliser notre propre format d'assertion. Nous commen&ccedil;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&eacute;era un objet qui parle le m&ecirc;me langage que votre testeur. Bien s&ucirc;r le truc c'est que nous cr&eacute;ons jamais un tel objet : le g&eacute;n&eacute;rateur s'en chargera. Nous avons juste besoin d'une ligne de code suppl&eacute;mentaire pour dire au g&eacute;n&eacute;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 &agrave; inclure <em>my_mock.php</em> &agrave; la place de la version par d&eacute;faut <em>simple_mock.php</em> et vous pouvez introduire des objets fantaisie dans votre suite de tests existants.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>