close Warning: Can't use blame annotator:
svn blame failed on trunk/server/www/vendors/simpletest/docs/en/web_tester_documentation.html: ("Can't find a temporary directory: Internal error", 20014)

source: trunk/server/www/vendors/simpletest/docs/en/web_tester_documentation.html @ 6

Last change on this file since 6 was 6, checked in by sander, 12 years ago

Added SimpleTest? test framework

File size: 22.1 KB
RevLine 
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Simple Test for PHP web script testing documentation</title>
5<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
6</head>
7<body>
8<div class="menu_back"><div class="menu">
9<a href="index.html">SimpleTest</a>
10                |
11                <a href="overview.html">Overview</a>
12                |
13                <a href="unit_test_documentation.html">Unit tester</a>
14                |
15                <a href="group_test_documentation.html">Group tests</a>
16                |
17                <a href="mock_objects_documentation.html">Mock objects</a>
18                |
19                <a href="partial_mocks_documentation.html">Partial mocks</a>
20                |
21                <a href="reporter_documentation.html">Reporting</a>
22                |
23                <a href="expectation_documentation.html">Expectations</a>
24                |
25                <span class="chosen">Web tester</span>
26                |
27                <a href="form_testing_documentation.html">Testing forms</a>
28                |
29                <a href="authentication_documentation.html">Authentication</a>
30                |
31                <a href="browser_documentation.html">Scriptable browser</a>
32</div></div>
33<h1>Web tester documentation</h1>
34        This page...
35        <ul>
36<li>
37            Successfully <a href="#fetch">fetching a web page</a>
38        </li>
39<li>
40            Testing the <a href="#content">page content</a>
41        </li>
42<li>
43            <a href="#navigation">Navigating a web site</a>
44            while testing
45        </li>
46<li>
47            <a href="#request">Raw request modifications</a> and debugging methods
48        </li>
49</ul>
50<div class="content">
51        <p><a class="target" name="fetch"><h2>Fetching a page</h2></a></p>
52            <p>
53                Testing classes is all very well, but PHP is predominately
54                a language for creating functionality within web pages.
55                How do we test the front end presentation role of our PHP
56                applications?
57                Well the web pages are just text, so we should be able to
58                examine them just like any other test data.
59            </p>
60            <p>
61                This leads to a tricky issue.
62                If we test at too low a level, testing for matching tags
63                in the page with pattern matching for example, our tests will
64                be brittle.
65                The slightest change in layout could break a large number of
66                tests.
67                If we test at too high a level, say using mock versions of a
68                template engine, then we lose the ability to automate some classes
69                of test.
70                For example, the interaction of forms and navigation will
71                have to be tested manually.
72                These types of test are extremely repetitive and error prone.
73            </p>
74            <p>
75                SimpleTest includes a special form of test case for the testing
76                of web page actions.
77                The <span class="new_code">WebTestCase</span> includes facilities
78                for navigation, content and cookie checks and form handling.
79                Usage of these test cases is similar to the
80                <a href="unit_tester_documentation.html">UnitTestCase</a>...
81<pre>
82<strong>class TestOfLastcraft extends WebTestCase {
83}</strong>
84</pre>
85                Here we are about to test the
86                <a href="http://www.lastcraft.com/">Last Craft</a> site itself.
87                If this test case is in a file called <em>lastcraft_test.php</em>
88                then it can be loaded in a runner script just like unit tests...
89<pre>
90&lt;?php
91require_once('simpletest/autorun.php');<strong>
92require_once('simpletest/web_tester.php');</strong>
93SimpleTest::prefer(new TextReporter());
94
95class WebTests extends TestSuite {
96    function WebTests() {
97        $this-&gt;TestSuite('Web site tests');<strong>
98        $this-&gt;addFile('lastcraft_test.php');</strong>
99    }
100}
101?&gt;
102</pre>
103                I am using the text reporter here to more clearly
104                distinguish the web content from the test output.
105            </p>
106            <p>
107                Nothing is being tested yet.
108                We can fetch the home page by using the
109                <span class="new_code">get()</span> method...
110<pre>
111class TestOfLastcraft extends WebTestCase {
112    <strong>
113    function testHomepage() {
114        $this-&gt;assertTrue($this-&gt;get('http://www.lastcraft.com/'));
115    }</strong>
116}
117</pre>
118                The <span class="new_code">get()</span> method will
119                return true only if page content was successfully
120                loaded.
121                It is a simple, but crude way to check that a web page
122                was actually delivered by the web server.
123                However that content may be a 404 response and yet
124                our <span class="new_code">get()</span> method will still return true.
125            </p>
126            <p>
127                Assuming that the web server for the Last Craft site is up
128                (sadly not always the case), we should see...
129<pre class="shell">
130Web site tests
131OK
132Test cases run: 1/1, Failures: 0, Exceptions: 0
133</pre>
134                All we have really checked is that any kind of page was
135                returned.
136                We don't yet know if it was the right one.
137            </p>
138       
139        <p><a class="target" name="content"><h2>Testing page content</h2></a></p>
140            <p>
141                To confirm that the page we think we are on is actually the
142                page we are on, we need to verify the page content.
143<pre>
144class TestOfLastcraft extends WebTestCase {
145   
146    function testHomepage() {<strong>
147        $this-&gt;get('http://www.lastcraft.com/');
148        $this-&gt;assertText('Why the last craft');</strong>
149    }
150}
151</pre>
152                The page from the last fetch is held in a buffer in
153                the test case, so there is no need to refer to it directly.
154                The pattern match is always made against the buffer.
155            </p>
156            <p>
157                Here is the list of possible content assertions...
158                <table><tbody>
159                    <tr>
160<td><span class="new_code">assertTitle($title)</span></td>
161<td>Pass if title is an exact match</td>
162</tr>
163                    <tr>
164<td><span class="new_code">assertText($text)</span></td>
165<td>Pass if matches visible and "alt" text</td>
166</tr>
167                    <tr>
168<td><span class="new_code">assertNoText($text)</span></td>
169<td>Pass if doesn't match visible and "alt" text</td>
170</tr>
171                    <tr>
172<td><span class="new_code">assertPattern($pattern)</span></td>
173<td>A Perl pattern match against the page content</td>
174</tr>
175                    <tr>
176<td><span class="new_code">assertNoPattern($pattern)</span></td>
177<td>A Perl pattern match to not find content</td>
178</tr>
179                    <tr>
180<td><span class="new_code">assertLink($label)</span></td>
181<td>Pass if a link with this text is present</td>
182</tr>
183                    <tr>
184<td><span class="new_code">assertNoLink($label)</span></td>
185<td>Pass if no link with this text is present</td>
186</tr>
187                    <tr>
188<td><span class="new_code">assertLinkById($id)</span></td>
189<td>Pass if a link with this id attribute is present</td>
190</tr>
191                    <tr>
192<td><span class="new_code">assertNoLinkById($id)</span></td>
193<td>Pass if no link with this id attribute is present</td>
194</tr>
195                    <tr>
196<td><span class="new_code">assertField($name, $value)</span></td>
197<td>Pass if an input tag with this name has this value</td>
198</tr>
199                    <tr>
200<td><span class="new_code">assertFieldById($id, $value)</span></td>
201<td>Pass if an input tag with this id has this value</td>
202</tr>
203                    <tr>
204<td><span class="new_code">assertResponse($codes)</span></td>
205<td>Pass if HTTP response matches this list</td>
206</tr>
207                    <tr>
208<td><span class="new_code">assertMime($types)</span></td>
209<td>Pass if MIME type is in this list</td>
210</tr>
211                    <tr>
212<td><span class="new_code">assertAuthentication($protocol)</span></td>
213<td>Pass if the current challenge is this protocol</td>
214</tr>
215                    <tr>
216<td><span class="new_code">assertNoAuthentication()</span></td>
217<td>Pass if there is no current challenge</td>
218</tr>
219                    <tr>
220<td><span class="new_code">assertRealm($name)</span></td>
221<td>Pass if the current challenge realm matches</td>
222</tr>
223                    <tr>
224<td><span class="new_code">assertHeader($header, $content)</span></td>
225<td>Pass if a header was fetched matching this value</td>
226</tr>
227                    <tr>
228<td><span class="new_code">assertNoHeader($header)</span></td>
229<td>Pass if a header was not fetched</td>
230</tr>
231                    <tr>
232<td><span class="new_code">assertCookie($name, $value)</span></td>
233<td>Pass if there is currently a matching cookie</td>
234</tr>
235                    <tr>
236<td><span class="new_code">assertNoCookie($name)</span></td>
237<td>Pass if there is currently no cookie of this name</td>
238</tr>
239                </tbody></table>
240                As usual with the SimpleTest assertions, they all return
241                false on failure and true on pass.
242                They also allow an optional test message and you can embed
243                the original test message inside using "%s" inside
244                your custom message.
245            </p>
246            <p>
247                So now we could instead test against the title tag with...
248<pre>
249<strong>$this-&gt;assertTitle('The Last Craft? Web developer tutorials on PHP, Extreme programming and Object Oriented development');</strong>
250</pre>
251                ...or, if that is too long and fragile...
252<pre>
253<strong>$this-&gt;assertTitle(new PatternExpectation('/The Last Craft/'));</strong>
254</pre>
255                As well as the simple HTML content checks we can check
256                that the MIME type is in a list of allowed types with...
257<pre>
258<strong>$this-&gt;assertMime(array('text/plain', 'text/html'));</strong>
259</pre>
260                More interesting is checking the HTTP response code.
261                Like the MIME type, we can assert that the response code
262                is in a list of allowed values...
263<pre>
264class TestOfLastcraft extends WebTestCase {
265   
266    function testRedirects() {
267        $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
268        $this-&gt;assertResponse(200);&lt;/strong&gt;
269    }
270}
271</pre>
272                Here we are checking that the fetch is successful by
273                allowing only a 200 HTTP response.
274                This test will pass, but it is not actually correct to do so.
275                There is no page, instead the server issues a redirect.
276                The <span class="new_code">WebTestCase</span> will
277                automatically follow up to three such redirects.
278                The tests are more robust this way and we are usually
279                interested in the interaction with the pages rather
280                than their delivery.
281                If the redirects are of interest then this ability must
282                be disabled...
283<pre>
284class TestOfLastcraft extends WebTestCase {
285   
286    function testHomepage() {<strong>
287        $this-&gt;setMaximumRedirects(0);</strong>
288        $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
289        $this-&gt;assertResponse(200);
290    }
291}
292</pre>
293                The assertion now fails as expected...
294<pre class="shell">
295Web site tests
2961) Expecting response in [200] got [302]
297    in testhomepage
298    in testoflastcraft
299    in lastcraft_test.php
300FAILURES!!!
301Test cases run: 1/1, Failures: 1, Exceptions: 0
302</pre>
303                We can modify the test to correctly assert redirects with...
304<pre>
305class TestOfLastcraft extends WebTestCase {
306   
307    function testHomepage() {
308        $this-&gt;setMaximumRedirects(0);
309        $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
310        $this-&gt;assertResponse(<strong>array(301, 302, 303, 307)</strong>);
311    }
312}
313</pre>
314                This now passes.
315            </p>
316       
317        <p><a class="target" name="navigation"><h2>Navigating a web site</h2></a></p>
318            <p>
319                Users don't often navigate sites by typing in URLs, but by
320                clicking links and buttons.
321                Here we confirm that the contact details can be reached
322                from the home page...
323<pre>
324class TestOfLastcraft extends WebTestCase {
325    ...
326    function testContact() {
327        $this-&gt;get('http://www.lastcraft.com/');<strong>
328        $this-&gt;clickLink('About');
329        $this-&gt;assertTitle(new PatternExpectation('/About Last Craft/'));</strong>
330    }
331}
332</pre>
333                The parameter is the text of the link.
334            </p>
335            <p>
336                If the target is a button rather than an anchor tag, then
337                <span class="new_code">clickSubmit()</span> can be used
338                with the button title...
339<pre>
340<strong>$this-&gt;clickSubmit('Go!');</strong>
341</pre>
342                If you are not sure or don't care, the usual case, then just
343                use the <span class="new_code">click()</span> method...
344<pre>
345<strong>$this-&gt;click('Go!');</strong>
346</pre>
347            </p>
348            <p>
349                The list of navigation methods is...
350                <table><tbody>
351                    <tr>
352<td><span class="new_code">getUrl()</span></td>
353<td>The current location</td>
354</tr>
355                    <tr>
356<td><span class="new_code">get($url, $parameters)</span></td>
357<td>Send a GET request with these parameters</td>
358</tr>
359                    <tr>
360<td><span class="new_code">post($url, $parameters)</span></td>
361<td>Send a POST request with these parameters</td>
362</tr>
363                    <tr>
364<td><span class="new_code">head($url, $parameters)</span></td>
365<td>Send a HEAD request without replacing the page content</td>
366</tr>
367                    <tr>
368<td><span class="new_code">retry()</span></td>
369<td>Reload the last request</td>
370</tr>
371                    <tr>
372<td><span class="new_code">back()</span></td>
373<td>Like the browser back button</td>
374</tr>
375                    <tr>
376<td><span class="new_code">forward()</span></td>
377<td>Like the browser forward button</td>
378</tr>
379                    <tr>
380<td><span class="new_code">authenticate($name, $password)</span></td>
381<td>Retry after a challenge</td>
382</tr>
383                    <tr>
384<td><span class="new_code">restart()</span></td>
385<td>Restarts the browser as if a new session</td>
386</tr>
387                    <tr>
388<td><span class="new_code">getCookie($name)</span></td>
389<td>Gets the cookie value for the current context</td>
390</tr>
391                    <tr>
392<td><span class="new_code">ageCookies($interval)</span></td>
393<td>Ages current cookies prior to a restart</td>
394</tr>
395                    <tr>
396<td><span class="new_code">clearFrameFocus()</span></td>
397<td>Go back to treating all frames as one page</td>
398</tr>
399                    <tr>
400<td><span class="new_code">clickSubmit($label)</span></td>
401<td>Click the first button with this label</td>
402</tr>
403                    <tr>
404<td><span class="new_code">clickSubmitByName($name)</span></td>
405<td>Click the button with this name attribute</td>
406</tr>
407                    <tr>
408<td><span class="new_code">clickSubmitById($id)</span></td>
409<td>Click the button with this ID attribute</td>
410</tr>
411                    <tr>
412<td><span class="new_code">clickImage($label, $x, $y)</span></td>
413<td>Click an input tag of type image by title or alt text</td>
414</tr>
415                    <tr>
416<td><span class="new_code">clickImageByName($name, $x, $y)</span></td>
417<td>Click an input tag of type image by name</td>
418</tr>
419                    <tr>
420<td><span class="new_code">clickImageById($id, $x, $y)</span></td>
421<td>Click an input tag of type image by ID attribute</td>
422</tr>
423                    <tr>
424<td><span class="new_code">submitFormById($id)</span></td>
425<td>Submit a form without the submit value</td>
426</tr>
427                    <tr>
428<td><span class="new_code">clickLink($label, $index)</span></td>
429<td>Click an anchor by the visible label text</td>
430</tr>
431                    <tr>
432<td><span class="new_code">clickLinkById($id)</span></td>
433<td>Click an anchor by the ID attribute</td>
434</tr>
435                    <tr>
436<td><span class="new_code">getFrameFocus()</span></td>
437<td>The name of the currently selected frame</td>
438</tr>
439                    <tr>
440<td><span class="new_code">setFrameFocusByIndex($choice)</span></td>
441<td>Focus on a frame counting from 1</td>
442</tr>
443                    <tr>
444<td><span class="new_code">setFrameFocus($name)</span></td>
445<td>Focus on a frame by name</td>
446</tr>
447                </tbody></table>
448            </p>
449            <p>
450                The parameters in the <span class="new_code">get()</span>, <span class="new_code">post()</span> or
451                <span class="new_code">head()</span> methods are optional.
452                The HTTP HEAD fetch does not change the browser context, only loads
453                cookies.
454                This can be useful for when an image or stylesheet sets a cookie
455                for crafty robot blocking.
456            </p>
457            <p>
458                The <span class="new_code">retry()</span>, <span class="new_code">back()</span> and
459                <span class="new_code">forward()</span> commands work as they would on
460                your web browser.
461                They use the history to retry pages.
462                This can be handy for checking the effect of hitting the
463                back button on your forms.
464            </p>
465            <p>
466                The frame methods need a little explanation.
467                By default a framed page is treated just like any other.
468                Content will be searced for throughout the entire frameset,
469                so clicking a link will work no matter which frame
470                the anchor tag is in.
471                You can override this behaviour by focusing on a single
472                frame.
473                If you do that, all searches and actions will apply to that
474                frame alone, such as authentication and retries.
475                If a link or button is not in a focused frame then it cannot
476                be clicked.
477            </p>
478            <p>
479                Testing navigation on fixed pages only tells you when you
480                have broken an entire script.
481                For highly dynamic pages, such as for bulletin boards, this can
482                be crucial for verifying the correctness of the application.
483                For most applications though, the really tricky logic is usually in
484                the handling of forms and sessions.
485                Fortunately SimpleTest includes
486                <a href="form_testing_documentation.html">tools for testing web forms</a>
487                as well.
488            </p>
489       
490        <p><a class="target" name="request"><h2>Modifying the request</h2></a></p>
491            <p>
492                Although SimpleTest does not have the goal of testing networking
493                problems, it does include some methods to modify and debug
494                the requests it makes.
495                Here is another method list...
496                <table><tbody>
497                    <tr>
498<td><span class="new_code">getTransportError()</span></td>
499<td>The last socket error</td>
500</tr>
501                    <tr>
502<td><span class="new_code">showRequest()</span></td>
503<td>Dump the outgoing request</td>
504</tr>
505                    <tr>
506<td><span class="new_code">showHeaders()</span></td>
507<td>Dump the incoming headers</td>
508</tr>
509                    <tr>
510<td><span class="new_code">showSource()</span></td>
511<td>Dump the raw HTML page content</td>
512</tr>
513                    <tr>
514<td><span class="new_code">ignoreFrames()</span></td>
515<td>Do not load framesets</td>
516</tr>
517                    <tr>
518<td><span class="new_code">setCookie($name, $value)</span></td>
519<td>Set a cookie from now on</td>
520</tr>
521                    <tr>
522<td><span class="new_code">addHeader($header)</span></td>
523<td>Always add this header to the request</td>
524</tr>
525                    <tr>
526<td><span class="new_code">setMaximumRedirects($max)</span></td>
527<td>Stop after this many redirects</td>
528</tr>
529                    <tr>
530<td><span class="new_code">setConnectionTimeout($timeout)</span></td>
531<td>Kill the connection after this time between bytes</td>
532</tr>
533                    <tr>
534<td><span class="new_code">useProxy($proxy, $name, $password)</span></td>
535<td>Make requests via this proxy URL</td>
536</tr>
537                </tbody></table>
538                These methods are principally for debugging.
539            </p>
540       
541    </div>
542        References and related information...
543        <ul>
544<li>
545            SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
546        </li>
547<li>
548            SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
549        </li>
550<li>
551            The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
552            gives full detail on the classes and assertions available.
553        </li>
554</ul>
555<div class="menu_back"><div class="menu">
556<a href="index.html">SimpleTest</a>
557                |
558                <a href="overview.html">Overview</a>
559                |
560                <a href="unit_test_documentation.html">Unit tester</a>
561                |
562                <a href="group_test_documentation.html">Group tests</a>
563                |
564                <a href="mock_objects_documentation.html">Mock objects</a>
565                |
566                <a href="partial_mocks_documentation.html">Partial mocks</a>
567                |
568                <a href="reporter_documentation.html">Reporting</a>
569                |
570                <a href="expectation_documentation.html">Expectations</a>
571                |
572                <span class="chosen">Web tester</span>
573                |
574                <a href="form_testing_documentation.html">Testing forms</a>
575                |
576                <a href="authentication_documentation.html">Authentication</a>
577                |
578                <a href="browser_documentation.html">Scriptable browser</a>
579</div></div>
580<div class="copyright">
581            Copyright<br>Marcus Baker 2006
582        </div>
583</body>
584</html>
Note: See TracBrowser for help on using the repository browser.