+ SimpleTest's web browser component can be used not just + outside of the WebTestCase class, but also + independently of the SimpleTest framework itself. +
+ + ++ You can use the web browser in PHP scripts to confirm + services are up and running, or to extract information + from them at a regular basis. + For example, here is a small script to extract the current number of + open PHP 5 bugs from the PHP web site... +
+<?php
+ require_once('simpletest/browser.php');
+
+ $browser = &new SimpleBrowser();
+ $browser->get('http://php.net/');
+ $browser->clickLink('reporting bugs');
+ $browser->clickLink('statistics');
+ $page = $browser->clickLink('PHP 5 bugs only');
+ preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches);
+ print $matches[1];
+?>
+
+ There are simpler methods to do this particular example in PHP
+ of course.
+ For example you can just use the PHP file()
+ command against what here is a pretty fixed page.
+ However, using the web browser for scripts allows authentication,
+ correct handling of cookies, automatic loading of frames, redirects,
+ form submission and the ability to examine the page headers.
+ Such methods are fragile against a site that is constantly
+ evolving and you would want a more direct way of accessing
+ data in a permanent set up, but for simple tasks this can provide
+ a very rapid solution.
+
+ + All of the navigation methods used in the + WebTestCase + are present in the SimpleBrowser class, but + the assertions are replaced with simpler accessors. + Here is a full list of the page navigation methods... +
| addHeader($header) | Adds a header to every fetch | +
| useProxy($proxy, $username, $password) | Use this proxy from now on | +
| head($url, $parameters) | Perform a HEAD request | +
| get($url, $parameters) | Fetch a page with GET | +
| post($url, $parameters) | Fetch a page with POST | +
| clickLink($label) | Follows a link by label | +
| isLink($label) | See if a link is present by label | +
| clickLinkById($id) | Follows a link by attribute | +
| isLinkById($id) | See if a link is present by attribut | +
| getUrl() | Current URL of page or frame | +
| getTitle() | Page title | +
| getContent() | Raw page or frame | +
| getContentAsText() | HTML removed except for alt text | +
| retry() | Repeat the last request | +
| back() | Use the browser back button | +
| forward() | Use the browser forward button | +
| authenticate($username, $password) | Retry page or frame after a 401 response | +
| restart($date) | Restarts the browser for a new session | +
| ageCookies($interval) | Ages the cookies by the specified time | +
| setCookie($name, $value) | Sets an additional cookie | +
| getCookieValue($host, $path, $name) | Reads the most specific cookie | +
| getCurrentCookieValue($name) | Reads cookie for the current context | +
+ Navigating forms is similar to the + WebTestCase form navigation... +
| setField($name, $value) | Sets all form fields with that name | +
| setFieldById($id, $value) | Sets all form fields with that id | +
| getField($name) | Accessor for a form element value | +
| getFieldById($id) | Accessor for a form element value | +
| clickSubmit($label) | Submits form by button label | +
| clickSubmitByName($name) | Submits form by button attribute | +
| clickSubmitById($id) | Submits form by button attribute | +
| clickImage($label, $x, $y) | Clicks the image by alt text | +
| clickImageByName($name, $x, $y) | Clicks the image by attribute | +
| clickImageById($id, $x, $y) | Clicks the image by attribute | +
| submitFormById($id) | Submits by the form tag attribute | +
+ Within a page, individual frames can be selected. + If no selection is made then all the frames are merged together + in one large conceptual page. + The content of the current page will be a concatenation of all of the + frames in the order that they were specified in the "frameset" + tags. +
| getFrames() | A dump of the current frame structure | +
| getFrameFocus() | Current frame label or index | +
| setFrameFocusByIndex($choice) | Select a frame numbered from 1 | +
| setFrameFocus($name) | Select frame by label | +
| clearFrameFocus() | Treat all the frames as a single page | +
+ All of this functionality is great when we actually manage to fetch pages, + but that doesn't always happen. + To help figure out what went wrong, the browser has some methods to + aid in debugging... +
| setConnectionTimeout($timeout) | Close the socket on overrun | +
| getRequest() | Raw request header of page or frame | +
| getHeaders() | Raw response header of page or frame | +
| getTransportError() | Any socket level errors in the last fetch | +
| getResponseCode() | HTTP response of page or frame | +
| getMimeType() | Mime type of page or frame | +
| getAuthentication() | Authentication type in 401 challenge header | +
| getRealm() | Authentication realm in 401 challenge header | +
| setMaximumRedirects($max) | Number of redirects before page is loaded anyway | +
| setMaximumNestedFrames($max) | Protection against recursive framesets | +
| ignoreFrames() | Disables frames support | +
| useFrames() | Enables frames support | +
+
+Complex unit tests with multiple browsers
+
+
+ Anything that could be done in a + WebTestCase can + now be done in a UnitTestCase. + This means that we can freely mix domain object testing with the + web interface... +
+
+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');
+ }
+}
+
+ While this may be a useful temporary expediency, I am not a fan
+ of this type of testing.
+ The testing has cut across application layers, make it twice as
+ likely it will need refactoring when the code changes.
+
+ + A more useful case of where using the browser directly can be helpful + is where the WebTestCase cannot cope. + An example is where two browsers are needed at the same time. +
++ For example, say we want to disallow multiple simultaneous + usage of a site with the same username. + This test case will do the job... +
+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');
+ }
+}
+
+ You can also use the SimpleBrowser class
+ directly when you want to write test cases using a different
+ test tool than SimpleTest.
+
+
+