<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Documentation SimpleTest : le composant de navigation web scriptable</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 le navigateur scriptable</h1>
<div class="content">
        
            <p>
                Le composant de navigation web de SimpleTest peut &ecirc;tre utilis&eacute; non seulement &agrave; l'ext&eacute;rieur de la classe <span class="new_code">WebTestCase</span>, mais aussi ind&eacute;pendamment du frameword SimpleTest lui-m&ecirc;me.
            </p>
        
        <p>
<a class="target" name="script">
<h2>Le navigateur scriptable</h2>
</a>
</p>
            <p>
                Vous pouvez utiliser le navigateur web dans des scripts PHP pour confirmer que des services marchent bien comme il faut ou pour extraire des informations &agrave; partir de ceux-ci de fa&ccedil;on r&eacute;guli&egrave;re.
                Par exemple, voici un petit script pour extraire le nombre de bogues ouverts dans PHP 5 &agrave; partir du <a href="http://www.php.net/">site web PHP</a>...
<pre>
&lt;?php
    require_once('simpletest/browser.php');
    
    $browser = &amp;new SimpleBrowser();
    $browser-&gt;get('http://php.net/');
    $browser-&gt;clickLink('reporting bugs');
    $browser-&gt;clickLink('statistics');
    $browser-&gt;clickLink('PHP 5 bugs only');
    $page = $browser-&gt;getContent();
    preg_match('/status=Open.*?by=Any.*?(\d+)&lt;\/a&gt;/', $page, $matches);
    print $matches[1];
?&gt;
</pre>
                Bien s&ucirc;r Il y a des m&eacute;thodes plus simple pour r&eacute;aliser cet exemple en PHP. Par exemple, vous pourriez juste utiliser la commande PHP <span class="new_code">file()</span> sur ce qui est ici une page fixe. Cependant, en utilisant des scripts avec le navigateur web vous vous autorisez l'authentification, la gestion des cookies, le chargement automatique des fen&ecirc;tres, les redirections, la transmission de formulaire et la capacit&eacute; d'examiner les ent&ecirc;tes. De telles m&eacute;thodes sont fragiles dans un site en constante &eacute;volution et vous voudrez employer une m&eacute;thode plus directe pour acc&eacute;der aux donn&eacute;es de fa&ccedil;on permanente, mais pour des t&acirc;ches simples cette technique peut s'av&eacute;rer une solution tr&egrave;s rapide.
            </p>
            <p>
                Toutes les m&eacute;thode de navigation utilis&eacute;es dans <a href="web_tester_documentation.html">WebTestCase</a> sont pr&eacute;sente dans la classe <span class="new_code">SimpleBrowser</span>, mais les assertions sont remplac&eacute;es par de simples accesseurs. Voici une liste compl&egrave;te des m&eacute;thodes de navigation de page &agrave; page...
                <table>
<tbody>
                    <tr>
<td><span class="new_code">addHeader($header)</span></td><td>Ajouter une ent&ecirc;te &agrave; chaque t&eacute;l&eacute;chargement</td>
</tr>
                    <tr>
<td><span class="new_code">useProxy($proxy, $username, $password)</span></td><td>Utilise ce proxy &agrave; partir de maintenant</td>
</tr> 
                    <tr>
<td><span class="new_code">head($url, $parameters)</span></td><td>Effectue une requ&ecirc;te HEAD</td>
</tr>
                    <tr>
<td><span class="new_code">get($url, $parameters)</span></td><td>T&eacute;l&eacute;charge une page avec un GET</td>
</tr>
                    <tr>
<td><span class="new_code">post($url, $parameters)</span></td><td>T&eacute;l&eacute;charge une page avec un POST</td>
</tr>
                    <tr>
<td><span class="new_code">clickLink($label)</span></td><td>Suit un lien par son &eacute;tiquette</td>
</tr>
                    <tr>
<td><span class="new_code">isLink($label)</span></td><td>V&eacute;rifie si un lien avec cette &eacute;tiquette existe</td>
</tr>
                    <tr>
<td><span class="new_code">clickLinkById($id)</span></td><td>Suit un lien par son attribut d'identification</td>
</tr>
                    <tr>
<td><span class="new_code">isLinkById($id)</span></td><td>V&eacute;rifie si un lien avec cet attribut d'identification existe</td>
</tr>
                    <tr>
<td><span class="new_code">getUrl()</span></td><td>La page ou la fen&ecirc;tre URL en cours</td>
</tr>
                    <tr>
<td><span class="new_code">getTitle()</span></td><td>Le titre de la page</td>
</tr>
                    <tr>
<td><span class="new_code">getContent()</span></td><td>Le page ou la fen&ecirc;tre brute</td>
</tr>
                    <tr>
<td><span class="new_code">getContentAsText()</span></td><td>Sans code HTML &agrave; l'exception du text "alt"</td>
</tr>
                    <tr>
<td><span class="new_code">retry()</span></td><td>R&eacute;p&egrave;te la derni&egrave;re requ&ecirc;te</td>
</tr>
                    <tr>
<td><span class="new_code">back()</span></td><td>Utilise le bouton "pr&eacute;c&eacute;dent" du navigateur</td>
</tr>
                    <tr>
<td><span class="new_code">forward()</span></td><td>Utilise le bouton "suivant" du navigateur</td>
</tr>
                    <tr>
<td><span class="new_code">authenticate($username, $password)</span></td><td>Retente la page ou la fen&ecirc;tre apr&egrave;s une r&eacute;ponse 401</td>
</tr>
                    <tr>
<td><span class="new_code">restart($date)</span></td><td>Relance le navigateur pour une nouvelle session</td>
</tr>
                    <tr>
<td><span class="new_code">ageCookies($interval)</span></td><td>Change la date des cookies</td>
</tr>
                    <tr>
<td><span class="new_code">setCookie($name, $value)</span></td><td>Lance un nouveau cookie</td>
</tr>
                    <tr>
<td><span class="new_code">getCookieValue($host, $path, $name)</span></td><td>Lit le cookie le plus sp&eacute;cifique</td>
</tr>
                    <tr>
<td><span class="new_code">getCurrentCookieValue($name)</span></td><td>Lit le contenue du cookie en cours</td>
</tr>
                </tbody>
</table>
                Les m&eacute;thode <span class="new_code">SimpleBrowser::useProxy()</span> et <span class="new_code">SimpleBrowser::addHeader()</span> sont sp&eacute;ciales. Une fois appell&eacute;es, elles continuent &agrave; s'appliquer sur les t&eacute;l&eacute;chargements suivants.
            </p>
            <p>
                Naviguer dans les formulaires est similaire &agrave; la <a href="form_testing_documentation.html">navigation des formulaires via WebTestCase</a>...
                <table>
<tbody>
                    <tr>
<td><span class="new_code">setField($name, $value)</span></td><td>Modifie tous les champs avec ce nom</td>
</tr>
                    <tr>
<td><span class="new_code">setFieldById($id, $value)</span></td><td>Modifie tous les champs avec cet identifiant</td>
</tr>
                    <tr>
<td><span class="new_code">getField($name)</span></td><td>Accesseur de la valeur d'un &eacute;l&eacute;ment de formulaire</td>
</tr>
                    <tr>
<td><span class="new_code">getFieldById($id)</span></td><td>Accesseur de la valeur de l'&eacute;l&eacute;ment de formulaire avec cet identifiant</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmit($label)</span></td><td>Transmet le formulaire avec l'&eacute;tiquette de son bouton</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmitByName($name)</span></td><td>Transmet le formulaire avec l'attribut de son bouton</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmitById($id)</span></td><td>Transmet le formulaire avec l'identifiant de son bouton</td>
</tr>
                    <tr>
<td><span class="new_code">clickImage($label, $x, $y)</span></td><td>Clique sur l'image par son texte alternatif</td>
</tr>
                    <tr>
<td><span class="new_code">clickImageByName($name, $x, $y)</span></td><td>Clique sur l'image par son attribut</td>
</tr>
                    <tr>
<td><span class="new_code">clickImageById($id, $x, $y)</span></td><td>Clique sur l'image par son identifiant</td>
</tr>
                    <tr>
<td><span class="new_code">submitFormById($id)</span></td><td>Transmet le formulaire par son identifiant propre</td>
</tr>
                </tbody>
</table>
                A aujourd'hui il n'existe aucune m&eacute;thode pour lister les formulaires et les champs disponibles : ce sera probablement ajout&eacute; dans des versions successives de SimpleTest.
            </p>
            <p>
                A l'int&eacute;rieur d'une page, les fen&ecirc;tres individuelles peuvent &ecirc;tre s&eacute;lectionn&eacute;es. Si aucune s&eacute;lection n'est r&eacute;alis&eacute;e alors toutes les fen&ecirc;tres sont fusionn&eacute;es ensemble dans un unique et grande page. Le contenu de la page en cours sera une concat&eacute;nation des toutes les fen&ecirc;tres dans l'ordre sp&eacute;cifi&eacute; par les balises "frameset".
                <table>
<tbody>
                    <tr>
<td><span class="new_code">getFrames()</span></td><td>Un d&eacute;chargement de la structure de la fen&ecirc;tre courante</td>
</tr>
                    <tr>
<td><span class="new_code">getFrameFocus()</span></td><td>L'index ou l'&eacute;tiquette de la fen&ecirc;tre en courante</td>
</tr>
                    <tr>
<td><span class="new_code">setFrameFocusByIndex($choice)</span></td><td>S&eacute;lectionne la fen&ecirc;tre num&eacute;rot&eacute;e &agrave; partir de 1</td>
</tr>
                    <tr>
<td><span class="new_code">setFrameFocus($name)</span></td><td>S&eacute;lectionne une fen&ecirc;tre par son &eacute;tiquette</td>
</tr>
                    <tr>
<td><span class="new_code">clearFrameFocus()</span></td><td>Traite toutes les fen&ecirc;tres comme une seule page</td>
</tr>
                </tbody>
</table>
                Lorsqu'on est focalis&eacute; sur une fen&ecirc;tre unique, le contenu viendra de celle-ci uniquement. Cela comprend les liens &agrave; cliquer et les formulaires &agrave; transmettre.
            </p>
        
        <p>
<a class="target" name="deboguer">
<h2>O&ugrave; sont les erreurs ?</h2>
</a>
</p>
            <p>
                Toute cette masse de fonctionnalit&eacute;s est g&eacute;niale lorsqu'on arrive &agrave; bien t&eacute;l&eacute;charger les pages, mais ce n'est pas toujours &eacute;vident. Pour aider &agrave; d&eacute;couvrir les erreurs, le navigateur a aussi des m&eacute;thodes pour aider au d&eacute;bogage.
                <table>
<tbody>
                    <tr>
<td><span class="new_code">setConnectionTimeout($timeout)</span></td><td>Ferme la socket avec un d&eacute;lai trop long</td>
</tr>
                    <tr>
<td><span class="new_code">getRequest()</span></td><td>L'ent&ecirc;te de la requ&ecirc;te brute de la page ou de la fen&ecirc;tre</td>
</tr>
                    <tr>
<td><span class="new_code">getHeaders()</span></td><td>L'ent&ecirc;te de r&eacute;ponse de la page ou de la fen&ecirc;tre</td>
</tr>
                    <tr>
<td><span class="new_code">getTransportError()</span></td><td>N'importe quel erreur au niveau de la socket dans le dernier t&eacute;l&eacute;chargement</td>
</tr>
                    <tr>
<td><span class="new_code">getResponseCode()</span></td><td>La r&eacute;ponse HTTP de la page ou de la fen&ecirc;tre</td>
</tr>
                    <tr>
<td><span class="new_code">getMimeType()</span></td><td>Le type Mime de la page our de la fen&ecirc;tre</td>
</tr>
                    <tr>
<td><span class="new_code">getAuthentication()</span></td><td>Le type d'authenficiation dans l'ent&ecirc;te d'une provocation 401</td>
</tr>
                    <tr>
<td><span class="new_code">getRealm()</span></td><td>Le realm d'authentification dans l'ent&ecirc;te d'une provocation 401</td>
</tr>
                    <tr>
<td><span class="new_code">setMaximumRedirects($max)</span></td><td>Nombre de redirection avant que la page ne soit charg&eacute;e automatiquement</td>
</tr>
                    <tr>
<td><span class="new_code">setMaximumNestedFrames($max)</span></td><td>Protection contre des framesets r&eacute;cursifs</td>
</tr>
                    <tr>
<td><span class="new_code">ignoreFrames()</span></td><td>Neutralise le support des fen&ecirc;tres</td>
</tr>
                    <tr>
<td><span class="new_code">useFrames()</span></td><td>Autorise le support des fen&ecirc;tres</td>
</tr>
                </tbody>
</table>
                Les m&eacute;thodes <span class="new_code">SimpleBrowser::setConnectionTimeout()</span>, <span class="new_code">SimpleBrowser::setMaximumRedirects()</span>,<span class="new_code">SimpleBrowser::setMaximumNestedFrames()</span>, <span class="new_code">SimpleBrowser::ignoreFrames()</span> et <span class="new_code">SimpleBrowser::useFrames()</span> continuent &agrave; s'appliquer sur toutes les requ&ecirc;tes suivantes. Les autres m&eacute;thodes tiennent compte des fen&ecirc;tres. Cela veut dire que si une fen&ecirc;tre individuel ne se charge pas, il suffit de se diriger vers elle avec <span class="new_code">SimpleBrowser::setFrameFocus()</span> : ensuite on utilisera <span class="new_code">SimpleBrowser::getRequest()</span>, etc. pour voir ce qui se passe.
            </p>
        
        <p>
<a class="target" name="unit">
<h2>Tests unitaires complexes avec des navigateurs multiples</h2>
</a>
</p>
            <p>
                Tout ce qui peut &ecirc;tre fait dans <a href="web_tester_documentation.html">WebTestCase</a> peut maintenant &ecirc;tre fait dans un <a href="unit_tester_documentation.html">UnitTestCase</a>. Ce qui revient &agrave; dire que nous pouvons librement m&eacute;langer des tests sur des objets de domaine avec l'interface web...
<pre>
class TestOfRegistration extends UnitTestCase {
    function testNewUserAddedToAuthenticator() {
        $browser = &amp;new SimpleBrowser();
        $browser-&gt;get('http://my-site.com/register.php');
        $browser-&gt;setField('email', 'me@here');
        $browser-&gt;setField('password', 'Secret');
        $browser-&gt;clickSubmit('Register');
        
        $authenticator = &amp;new Authenticator();
        $member = &amp;$authenticator-&gt;findByEmail('me@here');
        $this-&gt;assertEqual($member-&gt;getPassword(), 'Secret');
    }
}
</pre>
                Bien que &ccedil;a puisse &ecirc;tre utile par convenance temporaire, je ne suis pas fan de ce genre de test. Ce test s'applique &agrave; sur plusieurs couches de l'application, &ccedil;a implique qu'il est plus que probable qu'il faudra le remanier lorsque le code change.
            </p>
            <p>
                Un cas plus utile d'utilisation directe du navigateur est le moment o&ugrave; le <span class="new_code">WebTestCase</span> ne peut plus suivre. Un exemple ? Quand deux navigateurs doivent &ecirc;tre utilis&eacute;s en m&ecirc;me temps.
            </p>
            <p>
                Par exemple, supposons que nous voulions interdire des usages simultan&eacute;s d'un site avec le m&ecirc;me login d'identification. Ce sc&eacute;nario de test le v&eacute;rifie...
<pre>
class TestOfSecurity extends UnitTestCase {
    function testNoMultipleLoginsFromSameUser() {
        $first = &amp;new SimpleBrowser();
        $first-&gt;get('http://my-site.com/login.php');
        $first-&gt;setField('name', 'Me');
        $first-&gt;setField('password', 'Secret');
        $first-&gt;clickSubmit('Enter');
        $this-&gt;assertEqual($first-&gt;getTitle(), 'Welcome');
        
        $second = &amp;new SimpleBrowser();
        $second-&gt;get('http://my-site.com/login.php');
        $second-&gt;setField('name', 'Me');
        $second-&gt;setField('password', 'Secret');
        $second-&gt;clickSubmit('Enter');
        $this-&gt;assertEqual($second-&gt;getTitle(), 'Access Denied');
    }
}
</pre>
                Vous pouvez aussi utiliser la classe <span class="new_code">SimpleBrowser</span> quand vous souhaitez &eacute;crire des sc&eacute;narios de test en utilisant un autre outil que SimpleTest.
            </p>
        
    </div>
<div class="copyright">
            Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
        </div>
</body>
</html>