501 lines
21 KiB
HTML
501 lines
21 KiB
HTML
<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">
|
|
<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 le navigateur scriptable</h1>
|
|
This page...
|
|
<ul>
|
|
<li>
|
|
Utiliser le <a href="#scripting">navigateur web dans des scripts</a>
|
|
</li>
|
|
<li>
|
|
<a href="#deboguer">Déboguer</a> les erreurs sur les pages
|
|
</li>
|
|
<li>
|
|
<a href="#unit">Tests complexes avec des navigateurs web multiples</a>
|
|
</li>
|
|
</ul>
|
|
<div class="content">
|
|
|
|
<p>
|
|
Le composant de navigation web de SimpleTest peut être utilisé
|
|
non seulement à l'extérieur de la classe <span class="new_code">WebTestCase</span>,
|
|
mais aussi indépendamment du framework SimpleTest lui-même.
|
|
</p>
|
|
|
|
<h2>
|
|
<a class="target" name="script"></a>Le navigateur scriptable</h2>
|
|
<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 à partir de ceux-ci de façon régulière.
|
|
Par exemple, voici un petit script pour extraire
|
|
le nombre de bogues ouverts dans PHP 5 à partir
|
|
du <a href="http://www.php.net/">site web PHP</a>...
|
|
<pre>
|
|
<?php
|
|
require_once('simpletest/browser.php');
|
|
|
|
$browser = &new SimpleBrowser();
|
|
$browser->get('http://php.net/');
|
|
$browser->clickLink('reporting bugs');
|
|
$browser->clickLink('statistics');
|
|
$browser->clickLink('PHP 5 bugs only');
|
|
$page = $browser->getContent();
|
|
preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches);
|
|
print $matches[1];
|
|
?>
|
|
</pre>
|
|
Bien sûr Il y a des méthodes plus simple pour ré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êtres,
|
|
les redirections, la transmission de formulaires et la capacité
|
|
d'examiner les entêtes.
|
|
</p>
|
|
<p>
|
|
Ces méthodes qui se basent sur le contenu textuel des pages
|
|
sont fragiles dans un site en constante évolution
|
|
et vous voudrez employer une méthode plus directe
|
|
pour accéder aux données de façon permanente,
|
|
mais pour des tâches simples cette technique peut s'avérer
|
|
une solution très rapide.
|
|
</p>
|
|
<p>
|
|
Toutes les méthode de navigation utilisées dans <a href="web_tester_documentation.html">WebTestCase</a> sont présente dans la classe <span class="new_code">SimpleBrowser</span>, mais les assertions sont remplacées par de simples accesseurs. Voici une liste complète des méthodes de navigation de page à page...
|
|
<table><tbody>
|
|
<tr>
|
|
<td><span class="new_code">addHeader($header)</span></td>
|
|
<td>Ajouter une entête à chaque téléchargement</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">useProxy($proxy, $username, $password)</span></td>
|
|
<td>Utilise ce proxy à partir de maintenant</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">head($url, $parameters)</span></td>
|
|
<td>Effectue une requête HEAD</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">get($url, $parameters)</span></td>
|
|
<td>Télécharge une page avec un GET</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">post($url, $parameters)</span></td>
|
|
<td>Télécharge une page avec un POST</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">click($label)</span></td>
|
|
<td>Suit un lien visible ou un bouton texte par son étiquette</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">clickLink($label)</span></td>
|
|
<td>Suit un lien par son étiquette</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">isLink($label)</span></td>
|
|
<td>Vérifie l'existance d'un lien par son étiquette</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érifie l'existance d'un lien par son attribut d'identification</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getUrl()</span></td>
|
|
<td>La page ou la fenê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être brute</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getContentAsText()</span></td>
|
|
<td>Sans code HTML à l'exception du text "alt"</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">retry()</span></td>
|
|
<td>Répète la dernière requête</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">back()</span></td>
|
|
<td>Utilise le bouton "précé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être après une ré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é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éthode <span class="new_code">SimpleBrowser::useProxy()</span> et
|
|
<span class="new_code">SimpleBrowser::addHeader()</span> sont spéciales.
|
|
Une fois appelées, elles continuent à s'appliquer sur les téléchargements suivants.
|
|
</p>
|
|
<p>
|
|
Naviguer dans les formulaires est similaire à la <a href="form_testing_documentation.html">navigation des formulaires via WebTestCase</a>...
|
|
<table><tbody>
|
|
<tr>
|
|
<td><span class="new_code">setField($label, $value)</span></td>
|
|
<td>Modifie tous les champs avec cette étiquette ou ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">setFieldByName($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($label)</span></td>
|
|
<td>Accesseur de la valeur d'un élément de formulaire avec cette étiquette ou ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getFieldByName($name)</span></td>
|
|
<td>Accesseur de la valeur d'un élément de formulaire avec ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getFieldById($id)</span></td>
|
|
<td>Accesseur de la valeur de l'élément de formulaire avec cet identifiant</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">clickSubmit($label)</span></td>
|
|
<td>Transmet le formulaire avec l'é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 une balise input de type image par son titre (title="*") our son texte alternatif (alt="*")</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">clickImageByName($name, $x, $y)</span></td>
|
|
<td>Clique sur une balise input de type image par son attribut (name="*")</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">clickImageById($id, $x, $y)</span></td>
|
|
<td>Clique sur une balise input de type image par son identifiant (id="*")</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">submitFormById($id)</span></td>
|
|
<td>Transmet le formulaire par son identifiant propre</td>
|
|
</tr>
|
|
</tbody></table>
|
|
Au jourd d'aujourd'hui il n'existe pas beaucoup de méthodes pour lister
|
|
les formulaires et les champs disponibles.
|
|
<table><tbody>
|
|
<tr>
|
|
<td><span class="new_code">isClickable($label)</span></td>
|
|
<td>Vérifie si un lien existe avec cette étiquette ou ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">isSubmit($label)</span></td>
|
|
<td>Vérifie si un bouton existe avec cette étiquette ou ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">isImage($label)</span></td>
|
|
<td>Vérifie si un bouton image existe avec cette étiquette ou ce nom</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getLink($label)</span></td>
|
|
<td>Trouve une URL à partir de son label</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getLinkById($label)</span></td>
|
|
<td>Trouve une URL à partir de son identifiant</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getUrls()</span></td>
|
|
<td>Liste l'ensemble des liens de la page courante</td>
|
|
</tr>
|
|
</tbody></table>
|
|
Ce sera probablement
|
|
ajouté dans des versions successives de SimpleTest.
|
|
</p>
|
|
<p>
|
|
A l'intérieur d'une page, les fenêtres individuelles peuvent être
|
|
sélectionnées. Si aucune sélection n'est réalisée alors
|
|
toutes les fenêtres sont fusionnées ensemble dans
|
|
une unique et grande page.
|
|
Le contenu de la page en cours sera une concaténation des
|
|
toutes les fenêtres dans l'ordre spécifié par les balises "frameset".
|
|
<table><tbody>
|
|
<tr>
|
|
<td><span class="new_code">getFrames()</span></td>
|
|
<td>Un déchargement de la structure de la fenêtre courante</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getFrameFocus()</span></td>
|
|
<td>L'index ou l'étiquette de la fenêtre en courante</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">setFrameFocusByIndex($choice)</span></td>
|
|
<td>Sélectionne la fenêtre numérotée à partir de 1</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">setFrameFocus($name)</span></td>
|
|
<td>Sélectionne une fenêtre par son étiquette</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">clearFrameFocus()</span></td>
|
|
<td>Traite toutes les fenêtres comme une seule page</td>
|
|
</tr>
|
|
</tbody></table>
|
|
Lorsqu'on est focalisé sur une fenêtre unique,
|
|
le contenu viendra de celle-ci uniquement.
|
|
Cela comprend les liens à cliquer et les formulaires à transmettre.
|
|
</p>
|
|
|
|
<h2>
|
|
<a class="target" name="deboguer"></a>Où sont les erreurs ?</h2>
|
|
<p>
|
|
Toute cette masse de fonctionnalités est géniale
|
|
lorsqu'on arrive à bien télécharger les pages,
|
|
mais ce n'est pas toujours évident.
|
|
Pour aider à découvrir les erreurs, le navigateur a aussi
|
|
des méthodes pour aider au débogage.
|
|
<table><tbody>
|
|
<tr>
|
|
<td><span class="new_code">setConnectionTimeout($timeout)</span></td>
|
|
<td>Ferme la socket avec un délai trop long</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getUrl()</span></td>
|
|
<td>L'URL de la page chargée le plus récemment</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getRequest()</span></td>
|
|
<td>L'entête de la requête brute de la page ou de la fenêtre</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getHeaders()</span></td>
|
|
<td>L'entête de réponse de la page ou de la fenê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éléchargement</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getResponseCode()</span></td>
|
|
<td>La réponse HTTP de la page ou de la fenêtre</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getMimeType()</span></td>
|
|
<td>Le type Mime de la page our de la fenêtre</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getAuthentication()</span></td>
|
|
<td>Le type d'authentification dans l'entête d'une provocation 401</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getRealm()</span></td>
|
|
<td>Le realm d'authentification dans l'entête d'une provocation 401</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">getBaseUrl()</span></td>
|
|
<td>Uniquement la base de l'URL de la page chargée le plus récemment</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">setMaximumRedirects($max)</span></td>
|
|
<td>Nombre de redirections avant que la page ne soit chargée automatiquement</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">setMaximumNestedFrames($max)</span></td>
|
|
<td>Protection contre des framesets récursifs</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">ignoreFrames()</span></td>
|
|
<td>Neutralise le support des fenêtres</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="new_code">useFrames()</span></td>
|
|
<td>Autorise le support des fenêtres</td>
|
|
</tr>
|
|
</tbody></table>
|
|
Les mé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 à s'appliquer
|
|
sur toutes les requêtes suivantes.
|
|
Les autres méthodes tiennent compte des fenêtres.
|
|
Cela veut dire que si une fenêtre individuelle 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>
|
|
|
|
<h2>
|
|
<a class="target" name="unit"></a>Tests unitaires complexes avec des navigateurs multiples</h2>
|
|
<p>
|
|
Tout ce qui peut être fait dans
|
|
<a href="web_tester_documentation.html">WebTestCase</a> peut maintenant
|
|
être fait dans un <a href="unit_tester_documentation.html">UnitTestCase</a>.
|
|
Ce qui revient à dire que nous pouvons librement mélanger
|
|
des tests sur des objets de domaine avec l'interface web...
|
|
<pre><strong>
|
|
class TestOfRegistration extends UnitTestCase {
|
|
function testNewUserAddedToAuthenticator() {</strong>
|
|
$browser = new SimpleBrowser();
|
|
$browser->get('http://my-site.com/register.php');
|
|
$browser->setField('email', 'me@here');
|
|
$browser->setField('password', 'Secret');
|
|
$browser->clickSubmit('Register');
|
|
<strong>
|
|
$authenticator = new Authenticator();
|
|
$member = $authenticator->findByEmail('me@here');
|
|
$this->assertEqual($member->getPassword(), 'Secret');</strong>
|
|
}
|
|
}
|
|
</pre>
|
|
Bien que ça puisse être utile par convenance temporaire,
|
|
je ne suis pas fan de ce genre de test. Ce test s'applique
|
|
à plusieurs couches de l'application, ça implique qu'il est
|
|
plus que probable qu'il faudra le remanier lorsque le code changera.
|
|
</p>
|
|
<p>
|
|
Un cas plus utile d'utilisation directe du navigateur est
|
|
le moment où le <span class="new_code">WebTestCase</span> ne peut plus suivre.
|
|
Un exemple ? Quand deux navigateurs doivent être utilisés en même temps.
|
|
</p>
|
|
<p>
|
|
Par exemple, supposons que nous voulions interdire
|
|
des usages simultanés d'un site avec le même login d'identification.
|
|
Ce scénario de test le vérifie...
|
|
<pre>
|
|
class TestOfSecurity extends UnitTestCase {
|
|
function testNoMultipleLoginsFromSameUser() {
|
|
$first = &new SimpleBrowser();
|
|
$first->get('http://my-site.com/login.php');
|
|
$first->setField('name', 'Me');
|
|
$first->setField('password', 'Secret');
|
|
$first->clickSubmit('Enter');
|
|
$this->assertEqual($first->getTitle(), 'Welcome');
|
|
|
|
$second = &new SimpleBrowser();
|
|
$second->get('http://my-site.com/login.php');
|
|
$second->setField('name', 'Me');
|
|
$second->setField('password', 'Secret');
|
|
$second->clickSubmit('Enter');
|
|
$this->assertEqual($second->getTitle(), 'Access Denied');
|
|
}
|
|
}
|
|
</pre>
|
|
Vous pouvez aussi utiliser la classe <span class="new_code">SimpleBrowser</span>
|
|
quand vous souhaitez écrire des scénarios de test en utilisant
|
|
un autre outil que SimpleTest, comme PHPUnit par exemple.
|
|
</p>
|
|
|
|
</div>
|
|
References and related information...
|
|
<ul>
|
|
<li>
|
|
La page du projet SimpleTest sur
|
|
<a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
|
</li>
|
|
<li>
|
|
La page de téléchargement de SimpleTest sur
|
|
<a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
|
</li>
|
|
<li>
|
|
<a href="http://simpletest.org/api/">L'API de développeur pour SimpleTest</a>
|
|
donne tous les détails sur les classes et les assertions disponibles.
|
|
</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>
|