1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
<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 être utilisé non seulement à l'extérieur de la classe <span class="new_code">WebTestCase</span>, mais aussi indépendamment du frameword SimpleTest lui-mê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 à 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 formulaire et la capacité d'examiner les entêtes. De telles méthodes 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">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 si un lien avec cette é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é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ê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 appellé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($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 élément de formulaire</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 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éthode pour lister les formulaires et les champs disponibles : 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 un 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>
<p>
<a class="target" name="deboguer">
<h2>Où sont les erreurs ?</h2>
</a>
</p>
<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">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'authenficiation 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">setMaximumRedirects($max)</span></td><td>Nombre de redirection 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 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 ê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>
class TestOfRegistration extends UnitTestCase {
function testNewUserAddedToAuthenticator() {
$browser = &new SimpleBrowser();
$browser->get('http://my-site.com/register.php');
$browser->setField('email', 'me@here');
$browser->setField('password', 'Secret');
$browser->clickSubmit('Register');
$authenticator = &new Authenticator();
$member = &$authenticator->findByEmail('me@here');
$this->assertEqual($member->getPassword(), 'Secret');
}
}
</pre>
Bien que ça puisse être utile par convenance temporaire, je ne suis pas fan de ce genre de test. Ce test s'applique à sur plusieurs couches de l'application, ç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ù 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.
</p>
</div>
<div class="copyright">
Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
</div>
</body>
</html>
|