From 322bb9cd2be9e51422cb2b82684692e825c2bfb7 Mon Sep 17 00:00:00 2001 From: brettp Date: Fri, 2 Oct 2009 18:40:04 +0000 Subject: Added simpletest and start of unit tests. git-svn-id: http://code.elgg.org/elgg/trunk@3503 36083f99-b078-4883-b0ff-0f9b5a30f544 --- .../docs/en/web_tester_documentation.html | 584 +++++++++++++++++++++ 1 file changed, 584 insertions(+) create mode 100755 vendors/simpletest/docs/en/web_tester_documentation.html (limited to 'vendors/simpletest/docs/en/web_tester_documentation.html') diff --git a/vendors/simpletest/docs/en/web_tester_documentation.html b/vendors/simpletest/docs/en/web_tester_documentation.html new file mode 100755 index 000000000..2602dd56d --- /dev/null +++ b/vendors/simpletest/docs/en/web_tester_documentation.html @@ -0,0 +1,584 @@ + + + +Simple Test for PHP web script testing documentation + + + + +

Web tester documentation

+ This page... + +
+

Fetching a page

+

+ Testing classes is all very well, but PHP is predominately + a language for creating functionality within web pages. + How do we test the front end presentation role of our PHP + applications? + Well the web pages are just text, so we should be able to + examine them just like any other test data. +

+

+ This leads to a tricky issue. + If we test at too low a level, testing for matching tags + in the page with pattern matching for example, our tests will + be brittle. + The slightest change in layout could break a large number of + tests. + If we test at too high a level, say using mock versions of a + template engine, then we lose the ability to automate some classes + of test. + For example, the interaction of forms and navigation will + have to be tested manually. + These types of test are extremely repetitive and error prone. +

+

+ SimpleTest includes a special form of test case for the testing + of web page actions. + The WebTestCase includes facilities + for navigation, content and cookie checks and form handling. + Usage of these test cases is similar to the + UnitTestCase... +

+class TestOfLastcraft extends WebTestCase {
+}
+
+ Here we are about to test the + Last Craft site itself. + If this test case is in a file called lastcraft_test.php + then it can be loaded in a runner script just like unit tests... +
+<?php
+require_once('simpletest/autorun.php');
+require_once('simpletest/web_tester.php');
+SimpleTest::prefer(new TextReporter());
+
+class WebTests extends TestSuite {
+    function WebTests() {
+        $this->TestSuite('Web site tests');
+        $this->addFile('lastcraft_test.php');
+    }
+}
+?>
+
+ I am using the text reporter here to more clearly + distinguish the web content from the test output. +

+

+ Nothing is being tested yet. + We can fetch the home page by using the + get() method... +

+class TestOfLastcraft extends WebTestCase {
+    
+    function testHomepage() {
+        $this->assertTrue($this->get('http://www.lastcraft.com/'));
+    }
+}
+
+ The get() method will + return true only if page content was successfully + loaded. + It is a simple, but crude way to check that a web page + was actually delivered by the web server. + However that content may be a 404 response and yet + our get() method will still return true. +

+

+ Assuming that the web server for the Last Craft site is up + (sadly not always the case), we should see... +

+Web site tests
+OK
+Test cases run: 1/1, Failures: 0, Exceptions: 0
+
+ All we have really checked is that any kind of page was + returned. + We don't yet know if it was the right one. +

+ +

Testing page content

+

+ To confirm that the page we think we are on is actually the + page we are on, we need to verify the page content. +

+class TestOfLastcraft extends WebTestCase {
+    
+    function testHomepage() {
+        $this->get('http://www.lastcraft.com/');
+        $this->assertText('Why the last craft');
+    }
+}
+
+ The page from the last fetch is held in a buffer in + the test case, so there is no need to refer to it directly. + The pattern match is always made against the buffer. +

+

+ Here is the list of possible content assertions... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
assertTitle($title)Pass if title is an exact match
assertText($text)Pass if matches visible and "alt" text
assertNoText($text)Pass if doesn't match visible and "alt" text
assertPattern($pattern)A Perl pattern match against the page content
assertNoPattern($pattern)A Perl pattern match to not find content
assertLink($label)Pass if a link with this text is present
assertNoLink($label)Pass if no link with this text is present
assertLinkById($id)Pass if a link with this id attribute is present
assertNoLinkById($id)Pass if no link with this id attribute is present
assertField($name, $value)Pass if an input tag with this name has this value
assertFieldById($id, $value)Pass if an input tag with this id has this value
assertResponse($codes)Pass if HTTP response matches this list
assertMime($types)Pass if MIME type is in this list
assertAuthentication($protocol)Pass if the current challenge is this protocol
assertNoAuthentication()Pass if there is no current challenge
assertRealm($name)Pass if the current challenge realm matches
assertHeader($header, $content)Pass if a header was fetched matching this value
assertNoHeader($header)Pass if a header was not fetched
assertCookie($name, $value)Pass if there is currently a matching cookie
assertNoCookie($name)Pass if there is currently no cookie of this name
+ As usual with the SimpleTest assertions, they all return + false on failure and true on pass. + They also allow an optional test message and you can embed + the original test message inside using "%s" inside + your custom message. +

+

+ So now we could instead test against the title tag with... +

+$this->assertTitle('The Last Craft? Web developer tutorials on PHP, Extreme programming and Object Oriented development');
+
+ ...or, if that is too long and fragile... +
+$this->assertTitle(new PatternExpectation('/The Last Craft/'));
+
+ As well as the simple HTML content checks we can check + that the MIME type is in a list of allowed types with... +
+$this->assertMime(array('text/plain', 'text/html'));
+
+ More interesting is checking the HTTP response code. + Like the MIME type, we can assert that the response code + is in a list of allowed values... +
+class TestOfLastcraft extends WebTestCase {
+    
+    function testRedirects() {
+        $this->get('http://www.lastcraft.com/test/redirect.php');
+        $this->assertResponse(200);</strong>
+    }
+}
+
+ Here we are checking that the fetch is successful by + allowing only a 200 HTTP response. + This test will pass, but it is not actually correct to do so. + There is no page, instead the server issues a redirect. + The WebTestCase will + automatically follow up to three such redirects. + The tests are more robust this way and we are usually + interested in the interaction with the pages rather + than their delivery. + If the redirects are of interest then this ability must + be disabled... +
+class TestOfLastcraft extends WebTestCase {
+    
+    function testHomepage() {
+        $this->setMaximumRedirects(0);
+        $this->get('http://www.lastcraft.com/test/redirect.php');
+        $this->assertResponse(200);
+    }
+}
+
+ The assertion now fails as expected... +
+Web site tests
+1) Expecting response in [200] got [302]
+    in testhomepage
+    in testoflastcraft
+    in lastcraft_test.php
+FAILURES!!!
+Test cases run: 1/1, Failures: 1, Exceptions: 0
+
+ We can modify the test to correctly assert redirects with... +
+class TestOfLastcraft extends WebTestCase {
+    
+    function testHomepage() {
+        $this->setMaximumRedirects(0);
+        $this->get('http://www.lastcraft.com/test/redirect.php');
+        $this->assertResponse(array(301, 302, 303, 307));
+    }
+}
+
+ This now passes. +

+ +

Navigating a web site

+

+ Users don't often navigate sites by typing in URLs, but by + clicking links and buttons. + Here we confirm that the contact details can be reached + from the home page... +

+class TestOfLastcraft extends WebTestCase {
+    ...
+    function testContact() {
+        $this->get('http://www.lastcraft.com/');
+        $this->clickLink('About');
+        $this->assertTitle(new PatternExpectation('/About Last Craft/'));
+    }
+}
+
+ The parameter is the text of the link. +

+

+ If the target is a button rather than an anchor tag, then + clickSubmit() can be used + with the button title... +

+$this->clickSubmit('Go!');
+
+ If you are not sure or don't care, the usual case, then just + use the click() method... +
+$this->click('Go!');
+
+

+

+ The list of navigation methods is... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
getUrl()The current location
get($url, $parameters)Send a GET request with these parameters
post($url, $parameters)Send a POST request with these parameters
head($url, $parameters)Send a HEAD request without replacing the page content
retry()Reload the last request
back()Like the browser back button
forward()Like the browser forward button
authenticate($name, $password)Retry after a challenge
restart()Restarts the browser as if a new session
getCookie($name)Gets the cookie value for the current context
ageCookies($interval)Ages current cookies prior to a restart
clearFrameFocus()Go back to treating all frames as one page
clickSubmit($label)Click the first button with this label
clickSubmitByName($name)Click the button with this name attribute
clickSubmitById($id)Click the button with this ID attribute
clickImage($label, $x, $y)Click an input tag of type image by title or alt text
clickImageByName($name, $x, $y)Click an input tag of type image by name
clickImageById($id, $x, $y)Click an input tag of type image by ID attribute
submitFormById($id)Submit a form without the submit value
clickLink($label, $index)Click an anchor by the visible label text
clickLinkById($id)Click an anchor by the ID attribute
getFrameFocus()The name of the currently selected frame
setFrameFocusByIndex($choice)Focus on a frame counting from 1
setFrameFocus($name)Focus on a frame by name
+

+

+ The parameters in the get(), post() or + head() methods are optional. + The HTTP HEAD fetch does not change the browser context, only loads + cookies. + This can be useful for when an image or stylesheet sets a cookie + for crafty robot blocking. +

+

+ The retry(), back() and + forward() commands work as they would on + your web browser. + They use the history to retry pages. + This can be handy for checking the effect of hitting the + back button on your forms. +

+

+ The frame methods need a little explanation. + By default a framed page is treated just like any other. + Content will be searced for throughout the entire frameset, + so clicking a link will work no matter which frame + the anchor tag is in. + You can override this behaviour by focusing on a single + frame. + If you do that, all searches and actions will apply to that + frame alone, such as authentication and retries. + If a link or button is not in a focused frame then it cannot + be clicked. +

+

+ Testing navigation on fixed pages only tells you when you + have broken an entire script. + For highly dynamic pages, such as for bulletin boards, this can + be crucial for verifying the correctness of the application. + For most applications though, the really tricky logic is usually in + the handling of forms and sessions. + Fortunately SimpleTest includes + tools for testing web forms + as well. +

+ +

Modifying the request

+

+ Although SimpleTest does not have the goal of testing networking + problems, it does include some methods to modify and debug + the requests it makes. + Here is another method list... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
getTransportError()The last socket error
showRequest()Dump the outgoing request
showHeaders()Dump the incoming headers
showSource()Dump the raw HTML page content
ignoreFrames()Do not load framesets
setCookie($name, $value)Set a cookie from now on
addHeader($header)Always add this header to the request
setMaximumRedirects($max)Stop after this many redirects
setConnectionTimeout($timeout)Kill the connection after this time between bytes
useProxy($proxy, $name, $password)Make requests via this proxy URL
+ These methods are principally for debugging. +

+ +
+ References and related information... + + + + + -- cgit v1.2.3