summaryrefslogtreecommitdiff
path: root/tests/UnitTests/simpletest/docs/en
diff options
context:
space:
mode:
Diffstat (limited to 'tests/UnitTests/simpletest/docs/en')
-rw-r--r--tests/UnitTests/simpletest/docs/en/authentication_documentation.html320
-rw-r--r--tests/UnitTests/simpletest/docs/en/browser_documentation.html386
-rw-r--r--tests/UnitTests/simpletest/docs/en/docs.css84
-rw-r--r--tests/UnitTests/simpletest/docs/en/expectation_documentation.html356
-rw-r--r--tests/UnitTests/simpletest/docs/en/form_testing_documentation.html277
-rw-r--r--tests/UnitTests/simpletest/docs/en/group_test_documentation.html357
-rw-r--r--tests/UnitTests/simpletest/docs/en/index.html467
-rw-r--r--tests/UnitTests/simpletest/docs/en/mock_objects_documentation.html713
-rw-r--r--tests/UnitTests/simpletest/docs/en/overview.html422
-rw-r--r--tests/UnitTests/simpletest/docs/en/partial_mocks_documentation.html426
-rw-r--r--tests/UnitTests/simpletest/docs/en/reporter_documentation.html515
-rw-r--r--tests/UnitTests/simpletest/docs/en/server_stubs_documentation.html388
-rw-r--r--tests/UnitTests/simpletest/docs/en/unit_test_documentation.html387
-rw-r--r--tests/UnitTests/simpletest/docs/en/web_tester_documentation.html508
14 files changed, 0 insertions, 5606 deletions
diff --git a/tests/UnitTests/simpletest/docs/en/authentication_documentation.html b/tests/UnitTests/simpletest/docs/en/authentication_documentation.html
deleted file mode 100644
index a83f448b..00000000
--- a/tests/UnitTests/simpletest/docs/en/authentication_documentation.html
+++ /dev/null
@@ -1,320 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest documentation for testing log-in and authentication</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>
-<span class="chosen">Authentication</span>
-</li>
-<li>
-<a href="browser_documentation.html">Scriptable browser</a>
-</li>
-</ul>
-</div>
-</div>
-<h1>Authentication documentation</h1>
-<div class="content">
-
- <p>
- One of the trickiest, and yet most important, areas
- of testing web sites is the security.
- Testing these schemes is one of the core goals of
- the SimpleTest web tester.
- </p>
-
- <p>
-<a class="target" name="basic">
-<h2>Basic HTTP authentication</h2>
-</a>
-</p>
- <p>
- If you fetch a page protected by basic authentication then
- rather than receiving content, you will instead get a 401
- header.
- We can illustrate this with this test...
-<pre>
-class AuthenticationTest extends WebTestCase {<strong>
- function test401Header() {
- $this-&gt;get('http://www.lastcraft.com/protected/');
- $this-&gt;showHeaders();
- }</strong>
-}
-</pre>
- This allows us to see the challenge header...
- <div class="demo">
- <h1>File test</h1>
-<pre style="background-color: lightgray; color: black">
-HTTP/1.1 401 Authorization Required
-Date: Sat, 18 Sep 2004 19:25:18 GMT
-Server: Apache/1.3.29 (Unix) PHP/4.3.4
-WWW-Authenticate: Basic realm="SimpleTest basic authentication"
-Connection: close
-Content-Type: text/html; charset=iso-8859-1
-</pre>
- <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
- <strong>0</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
- </div>
- We are trying to get away from visual inspection though, and so SimpleTest
- allows to make automated assertions against the challenge.
- Here is a thorough test of our header...
-<pre>
-class AuthenticationTest extends WebTestCase {
- function test401Header() {
- $this-&gt;get('http://www.lastcraft.com/protected/');<strong>
- $this-&gt;assertAuthentication('Basic');
- $this-&gt;assertResponse(401);
- $this-&gt;assertRealm('SimpleTest basic authentication');</strong>
- }
-}
-</pre>
- Any one of these tests would normally do on it's own depending
- on the amount of detail you want to see.
- </p>
- <p>
- Most of the time we are not interested in testing the
- authentication itself, but want to get past it to test
- the pages underneath.
- As soon as the challenge has been issued we can reply with
- an authentication response...
-<pre>
-class AuthenticationTest extends WebTestCase {
- function testAuthentication() {
- $this-&gt;get('http://www.lastcraft.com/protected/');<strong>
- $this-&gt;authenticate('Me', 'Secret');</strong>
- $this-&gt;assertTitle(...);
- }
-}
-</pre>
- The username and password will now be sent with every
- subsequent request to that directory and subdirectories.
- You will have to authenticate again if you step outside
- the authenticated directory, but SimpleTest is smart enough
- to merge subdirectories into a common realm.
- </p>
- <p>
- You can shortcut this step further by encoding the log in
- details straight into the URL...
-<pre>
-class AuthenticationTest extends WebTestCase {
- function testCanReadAuthenticatedPages() {
- $this-&gt;get('http://<strong>Me:Secret@</strong>www.lastcraft.com/protected/');
- $this-&gt;assertTitle(...);
- }
-}
-</pre>
- If your username or password has special characters, then you
- will have to URL encode them or the request will not be parsed
- correctly.
- Also this header will not be sent on subsequent requests if
- you request a page with a fully qualified URL.
- If you navigate with relative URLs though, the authentication
- information will be preserved.
- </p>
- <p>
- Only basic authentication is currently supported and this is
- only really secure in tandem with HTTPS connections.
- This is usually enough to protect test server from prying eyes,
- however.
- Digest authentication and NTLM authentication may be added
- in the future.
- </p>
-
- <p>
-<a class="target" name="cookies">
-<h2>Cookies</h2>
-</a>
-</p>
- <p>
- Basic authentication doesn't give enough control over the
- user interface for web developers.
- More likely this functionality will be coded directly into
- the web architecture using cookies and complicated timeouts.
- </p>
- <p>
- Starting with a simple log-in form...
-<pre>
-&lt;form&gt;
- Username:
- &lt;input type="text" name="u" value="" /&gt;&lt;br /&gt;
- Password:
- &lt;input type="password" name="p" value="" /&gt;&lt;br /&gt;
- &lt;input type="submit" value="Log in" /&gt;
-&lt;/form&gt;
-</pre>
- Which looks like...
- </p>
- <p>
- <form class="demo">
- Username:
- <input type="text" name="u" value="">
-<br>
- Password:
- <input type="password" name="p" value="">
-<br>
- <input type="submit" value="Log in">
- </form>
- </p>
- <p>
- Let's suppose that in fetching this page a cookie has been
- set with a session ID.
- We are not going to fill the form in yet, just test that
- we are tracking the user.
- Here is the test...
-<pre>
-class LogInTest extends WebTestCase {
- function testSessionCookieSetBeforeForm() {
- $this-&gt;get('http://www.my-site.com/login.php');<strong>
- $this-&gt;assertCookie('SID');</strong>
- }
-}
-</pre>
- All we are doing is confirming that the cookie is set.
- As the value is likely to be rather cryptic it's not
- really worth testing this.
- </p>
- <p>
- The rest of the test would be the same as any other form,
- but we might want to confirm that we still have the same
- cookie after log-in as before we entered.
- We wouldn't want to lose track of this after all.
- Here is a possible test for this...
-<pre>
-class LogInTest extends WebTestCase {
- ...
- function testSessionCookieSameAfterLogIn() {
- $this-&gt;get('http://www.my-site.com/login.php');<strong>
- $session = $this-&gt;getCookie('SID');
- $this-&gt;setField('u', 'Me');
- $this-&gt;setField('p', 'Secret');
- $this-&gt;clickSubmit('Log in');
- $this-&gt;assertWantedPattern('/Welcome Me/');
- $this-&gt;assertCookie('SID', $session);</strong>
- }
-}
-</pre>
- This confirms that the session identifier is maintained
- afer log-in.
- </p>
- <p>
- We could even attempt to spoof our own system by setting
- arbitrary cookies to gain access...
-<pre>
-class LogInTest extends WebTestCase {
- ...
- function testSessionCookieSameAfterLogIn() {
- $this-&gt;get('http://www.my-site.com/login.php');<strong>
- $this-&gt;setCookie('SID', 'Some other session');
- $this-&gt;get('http://www.my-site.com/restricted.php');</strong>
- $this-&gt;assertWantedPattern('/Access denied/');
- }
-}
-</pre>
- Is your site protected from this attack?
- </p>
-
- <p>
-<a class="target" name="session">
-<h2>Browser sessions</h2>
-</a>
-</p>
- <p>
- If you are testing an authentication system a critical piece
- of behaviour is what happens when a user logs back in.
- We would like to simulate closing and reopening a browser...
-<pre>
-class LogInTest extends WebTestCase {
- ...
- function testLoseAuthenticationAfterBrowserClose() {
- $this-&gt;get('http://www.my-site.com/login.php');
- $this-&gt;setField('u', 'Me');
- $this-&gt;setField('p', 'Secret');
- $this-&gt;clickSubmit('Log in');
- $this-&gt;assertWantedPattern('/Welcome Me/');<strong>
-
- $this-&gt;restart();
- $this-&gt;get('http://www.my-site.com/restricted.php');
- $this-&gt;assertWantedPattern('/Access denied/');</strong>
- }
-}
-</pre>
- The <span class="new_code">WebTestCase::restart()</span> method will
- preserve cookies that have unexpired timeouts, but throw away
- those that are temporary or expired.
- You can optionally specify the time and date that the restart
- happened.
- </p>
- <p>
- Expiring cookies can be a problem.
- After all, if you have a cookie that expires after an hour,
- you don't want to stall the test for an hour while the
- cookie passes it's timeout.
- </p>
- <p>
- To push the cookies over the hour limit you can age them
- before you restart the session...
-<pre>
-class LogInTest extends WebTestCase {
- ...
- function testLoseAuthenticationAfterOneHour() {
- $this-&gt;get('http://www.my-site.com/login.php');
- $this-&gt;setField('u', 'Me');
- $this-&gt;setField('p', 'Secret');
- $this-&gt;clickSubmit('Log in');
- $this-&gt;assertWantedPattern('/Welcome Me/');
- <strong>
- $this-&gt;ageCookies(3600);</strong>
- $this-&gt;restart();
- $this-&gt;get('http://www.my-site.com/restricted.php');
- $this-&gt;assertWantedPattern('/Access denied/');
- }
-}
-</pre>
- After the restart it will appear that cookies are an
- hour older and any that pass their expiry will have
- disappeared.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/browser_documentation.html b/tests/UnitTests/simpletest/docs/en/browser_documentation.html
deleted file mode 100644
index 18c4d353..00000000
--- a/tests/UnitTests/simpletest/docs/en/browser_documentation.html
+++ /dev/null
@@ -1,386 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest documentation for the scriptable web browser component</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>
-<span class="chosen">Scriptable browser</span>
-</li>
-</ul>
-</div>
-</div>
-<h1>PHP Scriptable Web Browser</h1>
-<div class="content">
-
- <p>
- SimpleTest's web browser component can be used not just
- outside of the <span class="new_code">WebTestCase</span> class, but also
- independently of the SimpleTest framework itself.
- </p>
-
- <p>
-<a class="target" name="scripting">
-<h2>The Scriptable Browser</h2>
-</a>
-</p>
- <p>
- 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 <a href="http://www.php.net/">PHP web site</a>...
-<pre>
-<strong>&lt;?php
- require_once('simpletest/browser.php');
-
- $browser = &amp;new SimpleBrowser();
- $browser-&gt;get('http://php.net/');
- $browser-&gt;clickLink('reporting bugs');
- $browser-&gt;clickLink('statistics');
- $page = $browser-&gt;clickLink('PHP 5 bugs only');
- preg_match('/status=Open.*?by=Any.*?(\d+)&lt;\/a&gt;/', $page, $matches);
- print $matches[1];
-?&gt;</strong>
-</pre>
- There are simpler methods to do this particular example in PHP
- of course.
- For example you can just use the PHP <span class="new_code">file()</span>
- 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.
- </p>
- <p>
- All of the navigation methods used in the
- <a href="web_tester_documentation.html">WebTestCase</a>
- are present in the <span class="new_code">SimpleBrowser</span> class, but
- the assertions are replaced with simpler accessors.
- Here is a full list of the page navigation methods...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">addHeader($header)</span></td><td>Adds a header to every fetch</td>
-</tr>
- <tr>
-<td><span class="new_code">useProxy($proxy, $username, $password)</span></td><td>Use this proxy from now on</td>
-</tr>
- <tr>
-<td><span class="new_code">head($url, $parameters)</span></td><td>Perform a HEAD request</td>
-</tr>
- <tr>
-<td><span class="new_code">get($url, $parameters)</span></td><td>Fetch a page with GET</td>
-</tr>
- <tr>
-<td><span class="new_code">post($url, $parameters)</span></td><td>Fetch a page with POST</td>
-</tr>
- <tr>
-<td><span class="new_code">clickLink($label)</span></td><td>Follows a link by label</td>
-</tr>
- <tr>
-<td><span class="new_code">isLink($label)</span></td><td>See if a link is present by label</td>
-</tr>
- <tr>
-<td><span class="new_code">clickLinkById($id)</span></td><td>Follows a link by attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">isLinkById($id)</span></td><td>See if a link is present by attribut</td>
-</tr>
- <tr>
-<td><span class="new_code">getUrl()</span></td><td>Current URL of page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getTitle()</span></td><td>Page title</td>
-</tr>
- <tr>
-<td><span class="new_code">getContent()</span></td><td>Raw page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getContentAsText()</span></td><td>HTML removed except for alt text</td>
-</tr>
- <tr>
-<td><span class="new_code">retry()</span></td><td>Repeat the last request</td>
-</tr>
- <tr>
-<td><span class="new_code">back()</span></td><td>Use the browser back button</td>
-</tr>
- <tr>
-<td><span class="new_code">forward()</span></td><td>Use the browser forward button</td>
-</tr>
- <tr>
-<td><span class="new_code">authenticate($username, $password)</span></td><td>Retry page or frame after a 401 response</td>
-</tr>
- <tr>
-<td><span class="new_code">restart($date)</span></td><td>Restarts the browser for a new session</td>
-</tr>
- <tr>
-<td><span class="new_code">ageCookies($interval)</span></td><td>Ages the cookies by the specified time</td>
-</tr>
- <tr>
-<td><span class="new_code">setCookie($name, $value)</span></td><td>Sets an additional cookie</td>
-</tr>
- <tr>
-<td><span class="new_code">getCookieValue($host, $path, $name)</span></td><td>Reads the most specific cookie</td>
-</tr>
- <tr>
-<td><span class="new_code">getCurrentCookieValue($name)</span></td><td>Reads cookie for the current context</td>
-</tr>
- </tbody>
-</table>
- The methods <span class="new_code">SimpleBrowser::useProxy()</span> and
- <span class="new_code">SimpleBrowser::addHeader()</span> are special.
- Once called they continue to apply to all subsequent fetches.
- </p>
- <p>
- Navigating forms is similar to the
- <a href="form_testing_documentation.html">WebTestCase form navigation</a>...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">setField($name, $value)</span></td><td>Sets all form fields with that name</td>
-</tr>
- <tr>
-<td><span class="new_code">setFieldById($id, $value)</span></td><td>Sets all form fields with that id</td>
-</tr>
- <tr>
-<td><span class="new_code">getField($name)</span></td><td>Accessor for a form element value</td>
-</tr>
- <tr>
-<td><span class="new_code">getFieldById($id)</span></td><td>Accessor for a form element value</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmit($label)</span></td><td>Submits form by button label</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmitByName($name)</span></td><td>Submits form by button attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmitById($id)</span></td><td>Submits form by button attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImage($label, $x, $y)</span></td><td>Clicks the image by alt text</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImageByName($name, $x, $y)</span></td><td>Clicks the image by attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImageById($id, $x, $y)</span></td><td>Clicks the image by attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">submitFormById($id)</span></td><td>Submits by the form tag attribute</td>
-</tr>
- </tbody>
-</table>
- At the moment there aren't any methods to list available forms
- and fields.
- This will probably be added to later versions of SimpleTest.
- </p>
- <p>
- 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.
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">getFrames()</span></td><td>A dump of the current frame structure</td>
-</tr>
- <tr>
-<td><span class="new_code">getFrameFocus()</span></td><td>Current frame label or index</td>
-</tr>
- <tr>
-<td><span class="new_code">setFrameFocusByIndex($choice)</span></td><td>Select a frame numbered from 1</td>
-</tr>
- <tr>
-<td><span class="new_code">setFrameFocus($name)</span></td><td>Select frame by label</td>
-</tr>
- <tr>
-<td><span class="new_code">clearFrameFocus()</span></td><td>Treat all the frames as a single page</td>
-</tr>
- </tbody>
-</table>
- When focused on a single frame, the content will come from
- that frame only.
- This includes links to click and forms to submit.
- </p>
-
- <p>
-<a class="target" name="debug">
-<h2>What went wrong?</h2>
-</a>
-</p>
- <p>
- 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...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">setConnectionTimeout($timeout)</span></td><td>Close the socket on overrun</td>
-</tr>
- <tr>
-<td><span class="new_code">getRequest()</span></td><td>Raw request header of page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getHeaders()</span></td><td>Raw response header of page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getTransportError()</span></td><td>Any socket level errors in the last fetch</td>
-</tr>
- <tr>
-<td><span class="new_code">getResponseCode()</span></td><td>HTTP response of page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getMimeType()</span></td><td>Mime type of page or frame</td>
-</tr>
- <tr>
-<td><span class="new_code">getAuthentication()</span></td><td>Authentication type in 401 challenge header</td>
-</tr>
- <tr>
-<td><span class="new_code">getRealm()</span></td><td>Authentication realm in 401 challenge header</td>
-</tr>
- <tr>
-<td><span class="new_code">setMaximumRedirects($max)</span></td><td>Number of redirects before page is loaded anyway</td>
-</tr>
- <tr>
-<td><span class="new_code">setMaximumNestedFrames($max)</span></td><td>Protection against recursive framesets</td>
-</tr>
- <tr>
-<td><span class="new_code">ignoreFrames()</span></td><td>Disables frames support</td>
-</tr>
- <tr>
-<td><span class="new_code">useFrames()</span></td><td>Enables frames support</td>
-</tr>
- </tbody>
-</table>
- The methods <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> and
- <span class="new_code">SimpleBrowser::useFrames()</span> continue to apply
- to every subsequent request.
- The other methods are frames aware.
- This means that if you have an individual frame that is not
- loading, navigate to it using <span class="new_code">SimpleBrowser::setFrameFocus()</span>
- and you can then use <span class="new_code">SimpleBrowser::getRequest()</span>, etc to
- see what happened.
- </p>
-
- <p>
-<a class="target" name="unit">
-<h2>Complex unit tests with multiple browsers</h2>
-</a>
-</p>
- <p>
- Anything that could be done in a
- <a href="web_tester_documentation.html">WebTestCase</a> can
- now be done in a <a href="unit_tester_documentation.html">UnitTestCase</a>.
- This means that we can freely mix domain object testing with the
- web interface...
-<pre>
-<strong>
-class TestOfRegistration extends UnitTestCase {
- function testNewUserAddedToAuthenticator() {</strong>
- $browser = &amp;new SimpleBrowser();
- $browser-&gt;get('http://my-site.com/register.php');
- $browser-&gt;setField('email', 'me@here');
- $browser-&gt;setField('password', 'Secret');
- $browser-&gt;clickSubmit('Register');
- <strong>
- $authenticator = &amp;new Authenticator();
- $member = &amp;$authenticator-&gt;findByEmail('me@here');
- $this-&gt;assertEqual($member-&gt;getPassword(), 'Secret');
- }
-}</strong>
-</pre>
- 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.
- </p>
- <p>
- A more useful case of where using the browser directly can be helpful
- is where the <span class="new_code">WebTestCase</span> cannot cope.
- An example is where two browsers are needed at the same time.
- </p>
- <p>
- For example, say we want to disallow multiple simultaneous
- usage of a site with the same username.
- This test case will do the job...
-<pre>
-class TestOfSecurity extends UnitTestCase {
- function testNoMultipleLoginsFromSameUser() {<strong>
- $first = &amp;new SimpleBrowser();
- $first-&gt;get('http://my-site.com/login.php');
- $first-&gt;setField('name', 'Me');
- $first-&gt;setField('password', 'Secret');
- $first-&gt;clickSubmit('Enter');
- $this-&gt;assertEqual($first-&gt;getTitle(), 'Welcome');
-
- $second = &amp;new SimpleBrowser();
- $second-&gt;get('http://my-site.com/login.php');
- $second-&gt;setField('name', 'Me');
- $second-&gt;setField('password', 'Secret');
- $second-&gt;clickSubmit('Enter');
- $this-&gt;assertEqual($second-&gt;getTitle(), 'Access Denied');</strong>
- }
-}
-</pre>
- You can also use the <span class="new_code">SimpleBrowser</span> class
- directly when you want to write test cases using a different
- test tool than SimpleTest.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/docs.css b/tests/UnitTests/simpletest/docs/en/docs.css
deleted file mode 100644
index c59b9cd2..00000000
--- a/tests/UnitTests/simpletest/docs/en/docs.css
+++ /dev/null
@@ -1,84 +0,0 @@
-body {
- padding-left: 3%;
- padding-right: 3%;
-}
-pre {
- font-family: courier;
- font-size: 80%;
- border: 1px solid;
- background-color: #cccccc;
- padding: 5px;
- margin-left: 5%;
- margin-right: 8%;
-}
-.code, .new_code, pre.new_code {
- font-weight: bold;
-}
-div.copyright {
- font-size: 80%;
- color: gray;
-}
-div.copyright a {
- color: gray;
-}
-ul.api {
- padding-left: 0em;
- padding-right: 25%;
-}
-ul.api li {
- margin-top: 0.2em;
- margin-bottom: 0.2em;
- list-style: none;
- text-indent: -3em;
- padding-left: 3em;
-}
-div.demo {
- border: 4px ridge;
- border-color: gray;
- padding: 10px;
- margin: 5px;
- margin-left: 20px;
- margin-right: 40px;
- background-color: white;
-}
-div.demo span.fail {
- color: red;
-}
-div.demo span.pass {
- color: green;
-}
-div.demo h1 {
- font-size: 12pt;
- text-align: left;
- font-weight: bold;
-}
-table {
- border: 2px outset;
- border-color: gray;
- background-color: white;
- margin: 5px;
- margin-left: 5%;
- margin-right: 5%;
-}
-td {
- font-size: 80%;
-}
-.shell {
- color: white;
-}
-pre.shell {
- border: 4px ridge;
- border-color: gray;
- padding: 10px;
- margin: 5px;
- margin-left: 20px;
- margin-right: 40px;
- background-color: black;
-}
-form.demo {
- background-color: lightgray;
- border: 4px outset;
- border-color: lightgray;
- padding: 10px;
- margin-right: 40%;
-}
diff --git a/tests/UnitTests/simpletest/docs/en/expectation_documentation.html b/tests/UnitTests/simpletest/docs/en/expectation_documentation.html
deleted file mode 100644
index ed1484a9..00000000
--- a/tests/UnitTests/simpletest/docs/en/expectation_documentation.html
+++ /dev/null
@@ -1,356 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>
- Extending the SimpleTest unit tester with additional expectation classes
- </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>
-<span class="chosen">Expectations</span>
-</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>Expectation documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="mock">
-<h2>More control over mock objects</h2>
-</a>
-</p>
- <p>
- The default behaviour of the
- <a href="mock_objects_documentation.html">mock objects</a>
- in
- <a href="http://sourceforge.net/projects/simpletest/">SimpleTest</a>
- is either an identical match on the argument or to allow any argument at all.
- For almost all tests this is sufficient.
- Sometimes, though, you want to weaken a test case.
- </p>
- <p>
- One place where a test can be too tightly coupled is with
- text matching.
- Suppose we have a component that outputs a helpful error
- message when something goes wrong.
- You want to test that the correct error was sent, but the actual
- text may be rather long.
- If you test for the text exactly, then every time the exact wording
- of the message changes, you will have to go back and edit the test suite.
- </p>
- <p>
- For example, suppose we have a news service that has failed
- to connect to its remote source.
-<pre>
-<strong>class NewsService {
- ...
- function publish(&amp;$writer) {
- if (! $this-&gt;isConnected()) {
- $writer-&gt;write('Cannot connect to news service "' .
- $this-&gt;_name . '" at this time. ' .
- 'Please try again later.');
- }
- ...
- }
-}</strong>
-</pre>
- Here it is sending its content to a
- <span class="new_code">Writer</span> class.
- We could test this behaviour with a
- <span class="new_code">MockWriter</span> like so...
-<pre>
-class TestOfNewsService extends UnitTestCase {
- ...
- function testConnectionFailure() {<strong>
- $writer = &amp;new MockWriter($this);
- $writer-&gt;expectOnce('write', array(
- 'Cannot connect to news service ' .
- '"BBC News" at this time. ' .
- 'Please try again later.'));
-
- $service = &amp;new NewsService('BBC News');
- $service-&gt;publish($writer);
-
- $writer-&gt;tally();</strong>
- }
-}
-</pre>
- This is a good example of a brittle test.
- If we decide to add additional instructions, such as
- suggesting an alternative news source, we will break
- our tests even though no underlying functionality
- has been altered.
- </p>
- <p>
- To get around this, we would like to do a regular expression
- test rather than an exact match.
- We can actually do this with...
-<pre>
-class TestOfNewsService extends UnitTestCase {
- ...
- function testConnectionFailure() {
- $writer = &amp;new MockWriter($this);<strong>
- $writer-&gt;expectOnce(
- 'write',
- array(new WantedPatternExpectation('/cannot connect/i')));</strong>
-
- $service = &amp;new NewsService('BBC News');
- $service-&gt;publish($writer);
-
- $writer-&gt;tally();
- }
-}
-</pre>
- Instead of passing in the expected parameter to the
- <span class="new_code">MockWriter</span> we pass an
- expectation class called
- <span class="new_code">WantedPatternExpectation</span>.
- The mock object is smart enough to recognise this as special
- and to treat it differently.
- Rather than simply comparing the incoming argument to this
- object, it uses the expectation object itself to
- perform the test.
- </p>
- <p>
- The <span class="new_code">WantedPatternExpectation</span> takes
- the regular expression to match in its constructor.
- Whenever a comparison is made by the <span class="new_code">MockWriter</span>
- against this expectation class, it will do a
- <span class="new_code">preg_match()</span> with this pattern.
- With our test case above, as long as "cannot connect"
- appears in the text of the string, the mock will issue a pass
- to the unit tester.
- The rest of the text does not matter.
- </p>
- <p>
- The possible expectation classes are...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">EqualExpectation</span></td><td>An equality, rather than the stronger identity comparison</td>
-</tr>
- <tr>
-<td><span class="new_code">NotEqualExpectation</span></td><td>An inequality comparison</td>
-</tr>
- <tr>
-<td><span class="new_code">IndenticalExpectation</span></td><td>The default mock object check which must match exactly</td>
-</tr>
- <tr>
-<td><span class="new_code">NotIndenticalExpectation</span></td><td>Inverts the mock object logic</td>
-</tr>
- <tr>
-<td><span class="new_code">WantedPatternExpectation</span></td><td>Uses a Perl Regex to match a string</td>
-</tr>
- <tr>
-<td><span class="new_code">NoUnwantedPatternExpectation</span></td><td>Passes only if failing a Perl Regex</td>
-</tr>
- <tr>
-<td><span class="new_code">IsAExpectation</span></td><td>Checks the type or class name only</td>
-</tr>
- <tr>
-<td><span class="new_code">NotAExpectation</span></td><td>Opposite of the <span class="new_code">IsAExpectation</span></td>
-</tr>
- <tr>
-<td><span class="new_code">MethodExistsExpectation</span></td><td>Checks a method is available on an object</td>
-</tr>
- </tbody>
-</table>
- Most take the expected value in the constructor.
- The exceptions are the pattern matchers, which take a regular expression,
- and the <span class="new_code">IsAExpectation</span> and <span class="new_code">NotAExpectation</span> which takes a type
- or class name as a string.
- </p>
-
- <p>
-<a class="target" name="behaviour">
-<h2>Using expectations to control stubs</h2>
-</a>
-</p>
- <p>
- The expectation classes can be used not just for sending assertions
- from mock objects, but also for selecting behaviour for either
- the
- <a href="mock_objects_documentation.html">mock objects</a>
- or the
- <a href="server_stubs_documentation.html">server stubs</a>.
- Anywhere a list of arguments is given, a list of expectation objects
- can be inserted instead.
- </p>
- <p>
- Suppose we want an authorisation server stub to simulate a successful login
- only if it receives a valid session object.
- We can do this as follows...
-<pre>
-Stub::generate('Authorisation');
-<strong>
-$authorisation = new StubAuthorisation();
-$authorisation-&gt;setReturnValue(
- 'isAllowed',
- true,
- array(new IsAExpectation('Session', 'Must be a session')));
-$authorisation-&gt;setReturnValue('isAllowed', false);</strong>
-</pre>
- We have set the default stub behaviour to return false when
- <span class="new_code">isAllowed</span> is called.
- When we call the method with a single parameter that
- is a <span class="new_code">Session</span> object, it will return true.
- We have also added a second parameter as a message.
- This will be displayed as part of the mock object
- failure message if this expectation is the cause of
- a failure.
- </p>
- <p>
- This kind of sophistication is rarely useful, but is included for
- completeness.
- </p>
-
- <p>
-<a class="target" name="extending">
-<h2>Creating your own expectations</h2>
-</a>
-</p>
- <p>
- The expectation classes have a very simple structure.
- So simple that it is easy to create your own versions for
- commonly used test logic.
- </p>
- <p>
- As an example here is the creation of a class to test for
- valid IP addresses.
- In order to work correctly with the stubs and mocks the new
- expectation class should extend
- <span class="new_code">SimpleExpectation</span>...
-<pre>
-<strong>class ValidIp extends SimpleExpectation {
-
- function test($ip) {
- return (ip2long($ip) != -1);
- }
-
- function testMessage($ip) {
- return "Address [$ip] should be a valid IP address";
- }
-}</strong>
-</pre>
- There are only two methods to implement.
- The <span class="new_code">test()</span> method should
- evaluate to true if the expectation is to pass, and
- false otherwise.
- The <span class="new_code">testMessage()</span> method
- should simply return some helpful text explaining the test
- that was carried out.
- </p>
- <p>
- This class can now be used in place of the earlier expectation
- classes.
- </p>
-
- <p>
-<a class="target" name="unit">
-<h2>Under the bonnet of the unit tester</h2>
-</a>
-</p>
- <p>
- The <a href="http://sourceforge.net/projects/simpletest/">SimpleTest unit testing framework</a>
- also uses the expectation classes internally for the
- <a href="unit_test_documentation.html">UnitTestCase class</a>.
- We can also take advantage of these mechanisms to reuse our
- homebrew expectation classes within the test suites directly.
- </p>
- <p>
- The most crude way of doing this is to use the
- <span class="new_code">SimpleTest::assertExpectation()</span> method to
- test against it directly...
-<pre>
-<strong>class TestOfNetworking extends UnitTestCase {
- ...
- function testGetValidIp() {
- $server = &amp;new Server();
- $this-&gt;assertExpectation(
- new ValidIp(),
- $server-&gt;getIp(),
- 'Server IP address-&gt;%s');
- }
-}</strong>
-</pre>
- This is a little untidy compared with our usual
- <span class="new_code">assert...()</span> syntax.
- </p>
- <p>
- For such a simple case we would normally create a
- separate assertion method on our test case rather
- than bother using the expectation class.
- If we pretend that our expectation is a little more
- complicated for a moment, so that we want to reuse it,
- we get...
-<pre>
-class TestOfNetworking extends UnitTestCase {
- ...<strong>
- function assertValidIp($ip, $message = '%s') {
- $this-&gt;assertExpectation(new ValidIp(), $ip, $message);
- }</strong>
-
- function testGetValidIp() {
- $server = &amp;new Server();<strong>
- $this-&gt;assertValidIp(
- $server-&gt;getIp(),
- 'Server IP address-&gt;%s');</strong>
- }
-}
-</pre>
- It is unlikely we would ever need this degree of control
- over the testing machinery.
- It is rare to need the expectations for more than pattern
- matching.
- Also, complex expectation classes could make the tests
- harder to read and debug.
- These mechanisms are really of most use to authors of systems
- that will extend the test framework to create their own tool set.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/form_testing_documentation.html b/tests/UnitTests/simpletest/docs/en/form_testing_documentation.html
deleted file mode 100644
index 597db3b0..00000000
--- a/tests/UnitTests/simpletest/docs/en/form_testing_documentation.html
+++ /dev/null
@@ -1,277 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Simple Test documentation for testing HTML forms</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>
-<span class="chosen">Testing forms</span>
-</li>
-<li>
-<a href="authentication_documentation.html">Authentication</a>
-</li>
-<li>
-<a href="browser_documentation.html">Scriptable browser</a>
-</li>
-</ul>
-</div>
-</div>
-<h1>Form testing documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="submit">
-<h2>Submitting a simple form</h2>
-</a>
-</p>
- <p>
- When a page is fetched by the <span class="new_code">WebTestCase</span>
- using <span class="new_code">get()</span> or
- <span class="new_code">post()</span> the page content is
- automatically parsed.
- This results in any form controls that are inside &lt;form&gt; tags
- being available from within the test case.
- For example, if we have this snippet of HTML...
-<pre>
-&lt;form&gt;
- &lt;input type="text" name="a" value="A default" /&gt;
- &lt;input type="submit" value="Go" /&gt;
-&lt;/form&gt;
-</pre>
- Which looks like this...
- </p>
- <p>
- <form class="demo">
- <input type="text" name="a" value="A default">
- <input type="submit" value="Go">
- </form>
- </p>
- <p>
- We can navigate to this code, via the
- <a href="http://www.lastcraft.com/form_testing_documentation.php">LastCraft</a>
- site, with the following test...
-<pre>
-class SimpleFormTests extends WebTestCase {
- <strong>
- function testDefaultValue() {
- $this-&gt;get('http://www.lastcraft.com/form_testing_documentation.php');
- $this-&gt;assertField('a', 'A default');
- }</strong>
-}
-</pre>
- Immediately after loading the page all of the HTML controls are set at
- their default values just as they would appear in the web browser.
- The assertion tests that a HTML widget exists in the page with the
- name "a" and that it is currently set to the value
- "A default"
- </p>
- <p>
- We could submit the form straight away, but first we'll change
- the value of the text field and only then submit it...
-<pre>
-class SimpleFormTests extends WebTestCase {
-
- function testDefaultValue() {
- $this-&gt;get('http://www.my-site.com/');
- $this-&gt;assertField('a', 'A default');<strong>
- $this-&gt;setField('a', 'New value');
- $this-&gt;clickSubmit('Go');</strong>
- }
-}
-</pre>
- Because we didn't specify a method attribute on the form tag, and
- didn't specify an action either, the test case will follow
- the usual browser behaviour of submitting the form data as a <em>GET</em>
- request back to the same location.
- SimpleTest tries to emulate typical browser behaviour as much as possible,
- rather than attempting to catch missing attributes on tags.
- This is because the target of the testing framework is the PHP application
- logic, not syntax or other errors in the HTML code.
- For HTML errors, other tools such as
- <a href="http://www.w3.org/People/Raggett/tidy/">HTMLTidy</a> should be used.
- </p>
- <p>
- If a field is not present in any form, or if an option is unavailable,
- then <span class="new_code">WebTestCase::setField()</span> will return
- <span class="new_code">false</span>.
- For example, suppose we wish to verify that a "Superuser"
- option is not present in this form...
-<pre>
-&lt;strong&gt;Select type of user to add:&lt;/strong&gt;
-&lt;select name="type"&gt;
- &lt;option&gt;Subscriber&lt;/option&gt;
- &lt;option&gt;Author&lt;/option&gt;
- &lt;option&gt;Administrator&lt;/option&gt;
-&lt;/select&gt;
-</pre>
- Which looks like...
- </p>
- <p>
- <form class="demo">
- <strong>Select type of user to add:</strong>
- <select name="type">
- <option>Subscriber</option>
- <option>Author</option>
- <option>Administrator</option>
- </select>
- </form>
- </p>
- <p>
- The following test will confirm it...
-<pre>
-class SimpleFormTests extends WebTestCase {
- ...
- function testNoSuperuserChoiceAvailable() {<strong>
- $this-&gt;get('http://www.lastcraft.com/form_testing_documentation.php');
- $this-&gt;assertFalse($this-&gt;setField('type', 'Superuser'));</strong>
- }
-}
-</pre>
- The selection will not be changed on a failure to set
- a widget value.
- </p>
- <p>
- Here is the full list of widgets currently supported...
- <ul>
- <li>Text fields, including hidden and password fields.</li>
- <li>Submit buttons including the button tag, although not yet reset buttons</li>
- <li>Text area. This includes text wrapping behaviour.</li>
- <li>Checkboxes, including multiple checkboxes in the same form.</li>
- <li>Drop down selections, including multiple selects.</li>
- <li>Radio buttons.</li>
- <li>Images.</li>
- </ul>
- </p>
- <p>
- Although most standard HTML widgets are catered for by <em>SimpleTest</em>'s
- built in parser, it is unlikely that JavaScript will be implemented
- anytime soon.
- </p>
-
- <p>
-<a class="target" name="multiple">
-<h2>Fields with multiple values</h2>
-</a>
-</p>
- <p>
- SimpleTest can cope with two types of multivalue controls: Multiple
- selection drop downs, and multiple checkboxes with the same name
- within a form.
- The multivalue nature of these means that setting and testing
- are slightly different.
- Using checkboxes as an example...
-<pre>
-&lt;form class="demo"&gt;
- &lt;strong&gt;Create privileges allowed:&lt;/strong&gt;
- &lt;input type="checkbox" name="crud" value="c" checked&gt;&lt;br&gt;
- &lt;strong&gt;Retrieve privileges allowed:&lt;/strong&gt;
- &lt;input type="checkbox" name="crud" value="r" checked&gt;&lt;br&gt;
- &lt;strong&gt;Update privileges allowed:&lt;/strong&gt;
- &lt;input type="checkbox" name="crud" value="u" checked&gt;&lt;br&gt;
- &lt;strong&gt;Destroy privileges allowed:&lt;/strong&gt;
- &lt;input type="checkbox" name="crud" value="d" checked&gt;&lt;br&gt;
- &lt;input type="submit" value="Enable Privileges"&gt;
-&lt;/form&gt;
-</pre>
- Which renders as...
- </p>
- <p>
- <form class="demo">
- <strong>Create privileges allowed:</strong>
- <input type="checkbox" name="crud" value="c" checked>
-<br>
- <strong>Retrieve privileges allowed:</strong>
- <input type="checkbox" name="crud" value="r" checked>
-<br>
- <strong>Update privileges allowed:</strong>
- <input type="checkbox" name="crud" value="u" checked>
-<br>
- <strong>Destroy privileges allowed:</strong>
- <input type="checkbox" name="crud" value="d" checked>
-<br>
- <input type="submit" value="Enable Privileges">
- </form>
- </p>
- <p>
- If we wish to disable all but the retrieval privileges and
- submit this information we can do it like this...
-<pre>
-class SimpleFormTests extends WebTestCase {
- ...<strong>
- function testDisableNastyPrivileges() {
- $this-&gt;get('http://www.lastcraft.com/form_testing_documentation.php');
- $this-&gt;assertField('crud', array('c', 'r', 'u', 'd'));
- $this-&gt;setField('crud', array('r'));
- $this-&gt;clickSubmit('Enable Privileges');
- }</strong>
-}
-</pre>
- Instead of setting the field to a single value, we give it a list
- of values.
- We do the same when testing expected values.
- We can then write other test code to confirm the effect of this, perhaps
- by logging in as that user and attempting an update.
- </p>
- <p>
- <a class="target" name="raw">
-<h2>Raw posting</h2>
-</a>
- </p>
- <p>
- If you want to test a form handler, but have not yet written
- or do not have access to the form itself, you can create a
- form submission by hand.
-<pre>
-class SimpleFormTests extends WebTestCase {
- ...<strong>
- function testAttemptedHack() {
- $this-&gt;post(
- 'http://www.my-site.com/add_user.php',
- array('type' =&gt; 'superuser'));
- $this-&gt;assertNoUnwantedPattern('/user created/i');
- }</strong>
-}
-</pre>
- By adding data to the <span class="new_code">WebTestCase::post()</span>
- method, we are attempting to fetch the page as a form submission.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/group_test_documentation.html b/tests/UnitTests/simpletest/docs/en/group_test_documentation.html
deleted file mode 100644
index e7a067ec..00000000
--- a/tests/UnitTests/simpletest/docs/en/group_test_documentation.html
+++ /dev/null
@@ -1,357 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP group test documentation</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>
-<span class="chosen">Group tests</span>
-</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>Group Test documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="group">
-<h2>Grouping tests</h2>
-</a>
-</p>
- <p>
- To run test cases as part of a group the test cases should really
- be placed in files without the runner code...
-<pre>
-<strong>&lt;?php
- require_once('../classes/io.php');
-
- class FileTester extends UnitTestCase {
- ...
- }
-
- class SocketTester extends UnitTestCase {
- ...
- }
-?&gt;</strong>
-</pre>
- As many cases as needed can appear in a single file.
- They should include any code they need, such as the library
- being tested, but none of the simple test libraries.
- </p>
- <p>
- If you have extended any test cases, you can include them
- as well.
-<pre>
-&lt;?php
- require_once('../classes/io.php');
-<strong>
- class MyFileTestCase extends UnitTestCase {
- ...
- }
- SimpleTestOptions::ignore('MyFileTestCase');</strong>
-
- class FileTester extends MyFileTestCase {
- ...
- }
-
- class SocketTester extends UnitTestCase {
- ...
- }
-?&gt;
-</pre>
- The <span class="new_code">FileTester</span> class does
- not contain any actual tests, but is a base class for other
- test cases.
- For this reason we use the
- <span class="new_code">SimpleTestOptions::ignore()</span> directive
- to tell the upcoming group test to ignore it.
- This directive can appear anywhere in the file and works
- when a whole file of test cases is loaded (see below).
- We will call this sample <em>file_test.php</em>.
- </p>
- <p>
- Next we create a group test file, called say <em>group_test.php</em>.
- You will think of a better name I am sure.
- We will add the test file using a safe method...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');<strong>
- require_once('file_test.php');
-
- $test = &amp;new GroupTest('All file tests');
- $test-&gt;addTestCase(new FileTestCase());
- $test-&gt;run(new HtmlReporter());</strong>
-?&gt;
-</pre>
- This instantiates the test case before the test suite is
- run.
- This could get a little expensive with a large number of test
- cases, so another method is provided that will only
- instantiate the class when it is needed...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
- require_once('file_test.php');
-
- $test = &amp;new GroupTest('All file tests');<strong>
- $test-&gt;addTestClass('FileTestCase');</strong>
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- The problem with this method is that for every test case
- that we add we will have
- to <span class="new_code">require_once()</span> the test code
- file and manually instantiate each and every test case.
- We can save a lot of typing with...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
-
- $test = &amp;new GroupTest('All file tests');<strong>
- $test-&gt;addTestFile('file_test.php');</strong>
- $test-&gt;run(new HtmlReporter());
-?&amp;gt;
-</pre>
- What happens here is that the <span class="new_code">GroupTest</span>
- class has done the <span class="new_code">require_once()</span>
- for us.
- It then checks to see if any new test case classes
- have been created by the new file and automatically adds
- them to the group test.
- Now all we have to do is add each new file.
- </p>
- <p>
- There are two things that could go wrong and which require care...
- <ol>
- <li>
- The file could already have been parsed by PHP and so no
- new classes will have been added. You should make
- sure that the test cases are only included in this file
- and no others.
- </li>
- <li>
- New test case extension classes that get included will be
- placed in the group test and run also.
- You will need to add a <span class="new_code">SimpleTestOptions::ignore()</span>
- directive for these classes or make sure that they are included
- before the <span class="new_code">GroupTest::addTestFile()</span>
- line.
- </li>
- </ol>
- </p>
-
- <p>
-<a class="target" name="higher">
-<h2>Higher groupings</h2>
-</a>
-</p>
- <p>
- The above method places all of the test cases into one large group.
- For larger projects though this may not be flexible enough; you
- may want to group the tests in all sorts of ways.
- </p>
- <p>
- To get a more flexible group test we can subclass
- <span class="new_code">GroupTest</span> and then instantiate it as needed...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
- <strong>
- class FileGroupTest extends GroupTest {
- function FileGroupTest() {
- $this-&gt;GroupTest('All file tests');
- $this-&gt;addTestFile('file_test.php');
- }
- }</strong>
-?&gt;
-</pre>
- This effectively names the test in the constructor and then
- adds our test cases and a single group below.
- Of course we can add more than one group at this point.
- We can now invoke the tests from a separate runner file...
-<pre>
-&lt;?php
- require_once('file_group_test.php');
- <strong>
- $test = &amp;new FileGroupTest();
- $test-&gt;run(new HtmlReporter());</strong>
-?&gt;
-</pre>
- ...or we can group them into even larger group tests...
-<pre>
-&lt;?php
- require_once('file_group_test.php');
- <strong>
- $test = &amp;new BigGroupTest('Big group');
- $test-&gt;addTestCase(new FileGroupTest());
- $test-&gt;addTestCase(...);
- $test-&gt;run(new HtmlReporter());</strong>
-?&gt;
-</pre>
- If we still wish to run the original group test and we
- don't want all of these little runner files, we can
- put the test runner code around guard bars when we create
- each group.
-<pre>
-&lt;?php
- class FileGroupTest extends GroupTest {
- function FileGroupTest() {
- $this-&gt;GroupTest('All file tests');
- $test-&gt;addTestFile('file_test.php');
- }
- }
- <strong>
- if (! defined('RUNNER')) {
- define('RUNNER', true);</strong>
- $test = &amp;new FileGroupTest();
- $test-&gt;run(new HtmlReporter());
- }
-?&gt;
-</pre>
- This approach requires the guard to be set when including
- the group test file, but this is still less hassle than
- lots of separate runner files.
- You include the same guard on the top level tests to make sure
- that <span class="new_code">run()</span> will run once only
- from the top level script that has been invoked.
-<pre>
-&lt;?php<strong>
- define('RUNNER', true);</strong>
- require_once('file_group_test.php');
-
- $test = &amp;new BigGroupTest('Big group');
- $test-&gt;addTestCase(new FileGroupTest());
- $test-&gt;addTestCase(...);
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- As with the normal test cases, a <span class="new_code">GroupTest</span> can
- be loaded with the <span class="new_code">GroupTest::addTestFile()</span> method.
-<pre>
-&lt;?php
- define('RUNNER', true);
-
- $test = &amp;new BigGroupTest('Big group');<strong>
- $test-&gt;addTestFile('file_group_test.php');
- $test-&gt;addTestFile(...);</strong>
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- </p>
-
- <p>
-<a class="target" name="legacy">
-<h2>Integrating legacy test cases</h2>
-</a>
-</p>
- <p>
- If you already have unit tests for your code or are extending external
- classes that have tests, it is unlikely that all of the test cases
- are in SimpleTest format.
- Fortunately it is possible to incorporate test cases from other
- unit testers directly into SimpleTest group tests.
- </p>
- <p>
- Say we have the following
- <a href="http://sourceforge.net/projects/phpunit">PhpUnit</a>
- test case in the file <em>config_test.php</em>...
-<pre>
-<strong>class ConfigFileTest extends TestCase {
- function ConfigFileTest() {
- $this-&gt;TestCase('Config file test');
- }
-
- function testContents() {
- $config = new ConfigFile('test.conf');
- $this-&gt;assertRegexp('/me/', $config-&gt;getValue('username'));
- }
-}</strong>
-</pre>
- The group test can recognise this as long as we include
- the appropriate adapter class before we add the test
- file...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');<strong>
- require_once('simpletest/adapters/phpunit_test_case.php');</strong>
-
- $test = &amp;new GroupTest('All file tests');<strong>
- $test-&gt;addTestFile('config_test.php');</strong>
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- There are only two adapters, the other is for the
- <a href="http://pear.php.net/manual/en/package.php.phpunit.php">PEAR</a>
- 1.0 unit tester...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');<strong>
- require_once('simpletest/adapters/pear_test_case.php');</strong>
-
- $test = &amp;new GroupTest('All file tests');<strong>
- $test-&gt;addTestFile('some_pear_test_cases.php');</strong>
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- The PEAR test cases can be freely mixed with SimpleTest
- ones even in the same test file,
- but you cannot use SimpleTest assertions in the legacy
- test case versions.
- This is done as a check that you are not accidently making
- your test cases completely dependent on SimpleTest.
- You may want to do a PEAR release of your library for example
- which would mean shipping it with valid PEAR::PhpUnit test
- cases.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/index.html b/tests/UnitTests/simpletest/docs/en/index.html
deleted file mode 100644
index d5a30d31..00000000
--- a/tests/UnitTests/simpletest/docs/en/index.html
+++ /dev/null
@@ -1,467 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>
- Download the Simple Test testing framework -
- Unit tests and mock objects for PHP
- </title>
-<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
-</head>
-<body>
-<div class="menu_back">
-<div class="menu">
-<h2>
-<span class="chosen">SimpleTest</span>
-</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>Simple Test for PHP</h1>
-<div class="content">
-
-
- <p>
- The following assumes that you are familiar with the concept
- of unit testing as well as the PHP web development language.
- It is a guide for the impatient new user of
- <a href="https://sourceforge.net/project/showfiles.php?group_id=76550">SimpleTest</a>.
- For fuller documentation, especially if you are new
- to unit testing see the ongoing
- <a href="unit_test_documentation.html">documentation</a>, and for
- example test cases see the
- <a href="http://www.lastcraft.com/first_test_tutorial.php">unit testing tutorial</a>.
- </p>
-
- <p>
-<a class="target" name="unit">
-<h2>Using the tester quickly</h2>
-</a>
-</p>
- <p>
- Amongst software testing tools, a unit tester is the one
- closest to the developer.
- In the context of agile development the test code sits right
- next to the source code as both are written simultaneously.
- In this context SimpleTest aims to be a complete PHP developer
- test solution and is called "Simple" because it
- should be easy to use and extend.
- It wasn't a good choice of name really.
- It includes all of the typical functions you would expect from
- <a href="http://www.junit.org/">JUnit</a> and the
- <a href="http://sourceforge.net/projects/phpunit/">PHPUnit</a>
- ports, but also adds
- <a href="http://www.mockobjects.com">mock objects</a>.
- It has some <a href="http://sourceforge.net/projects/jwebunit/">JWebUnit</a>
- functionality as well.
- This includes web page navigation, cookie testing and form submission.
- </p>
- <p>
- The quickest way to demonstrate is with an example.
- </p>
- <p>
- Let us suppose we are testing a simple file logging class called
- <span class="new_code">Log</span> in <em>classes/log.php</em>.
- We start by creating a test script which we will call
- <em>tests/log_test.php</em> and populate it as follows...
-<pre>
-<strong>&lt;?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-?&gt;</strong>
-</pre>
- Here the <em>simpletest</em> folder is either local or in the path.
- You would have to edit these locations depending on where you
- placed the toolset.
- Next we create a test case...
-<pre>
-&lt;?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-<strong>
-class TestOfLogging extends UnitTestCase {
-}</strong>
-?&gt;
-</pre>
- Now we have five lines of scaffolding code and still no tests.
- However from this part on we get return on our investment very quickly.
- We'll assume that the <span class="new_code">Log</span> class
- takes the file name to write to in the constructor and we have
- a temporary folder in which to place this file...
-<pre>
-&lt;?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-
-class TestOfLogging extends UnitTestCase {
- <strong>
- function testCreatingNewFile() {
- @unlink('/temp/test.log');
- $log = new Log('/temp/test.log');
- $this-&gt;assertFalse(file_exists('/temp/test.log'));
- $log-&gt;message('Should write this to a file');
- $this-&gt;assertTrue(file_exists('/temp/test.log'));
- }</strong>
-}
-?&gt;
-</pre>
- When a test case runs it will search for any method that
- starts with the string <span class="new_code">test</span>
- and execute that method.
- We would normally have more than one test method of course.
- Assertions within the test methods trigger messages to the
- test framework which displays the result immediately.
- This immediate response is important, not just in the event
- of the code causing a crash, but also so that
- <span class="new_code">print</span> statements can display
- their content right next to the test case concerned.
- </p>
- <p>
- To see these results we have to actually run the tests.
- If this is the only test case we wish to run we can achieve
- it with...
-<pre>
-&lt;?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-
-class TestOfLogging extends UnitTestCase {
-
- function testCreatingNewFile() {
- @unlink('/temp/test.log');
- $log = new Log('/temp/test.log');
- $this-&gt;assertFalse(file_exists('/temp/test.log'));
- $log-&gt;message('Should write this to a file');
- $this-&gt;assertTrue(file_exists('/temp/test.log'));
- }
-}
-<strong>
-$test = &amp;new TestOfLogging();
-$test-&gt;run(new HtmlReporter());</strong>
-?&gt;
-</pre>
- </p>
- <p>
- On failure the display looks like this...
- <div class="demo">
- <h1>testoflogging</h1>
- <span class="fail">Fail</span>: testcreatingnewfile-&gt;True assertion failed.<br>
- <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
- <strong>1</strong> passes and <strong>1</strong> fails.</div>
- </div>
- ...and if it passes like this...
- <div class="demo">
- <h1>testoflogging</h1>
- <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
- <strong>2</strong> passes and <strong>0</strong> fails.</div>
- </div>
- And if you get this...
- <div class="demo">
- <b>Fatal error</b>: Failed opening required '../classes/log.php' (include_path='') in <b>/home/marcus/projects/lastcraft/tutorial_tests/Log/tests/log_test.php</b> on line <b>7</b>
- </div>
- it means you're missing the <em>classes/Log.php</em> file that could look like...
-<pre>
-&lt;?php
-class Log {
-
- function Log($file_path) {
- }
-
- function message() {
- }
-}
-?&gt;;
-</pre>
- </p>
-
- <p>
-<a class="target" name="group">
-<h2>Building group tests</h2>
-</a>
-</p>
- <p>
- It is unlikely in a real application that we will only ever run
- one test case.
- This means that we need a way of grouping cases into a test
- script that can, if need be, run every test in the application.
- </p>
- <p>
- Our first step is to strip the includes and to undo our
- previous hack...
-<pre>
-&lt;?php<strong>
-require_once('../classes/log.php');</strong>
-
-class TestOfLogging extends UnitTestCase {
-
- function testCreatingNewFile() {
- @unlink('/temp/test.log');
- $log = new Log('/temp/test.log');
- $this-&gt;assertFalse(file_exists('/temp/test.log'));
- $log-&gt;message('Should write this to a file');
- $this-&gt;assertTrue(file_exists('/temp/test.log'));<strong>
- }
-}
-?&gt;</strong>
-</pre>
- Next we create a new file called <em>tests/all_tests.php</em>
- and insert the following code...
-<pre>
-<strong>&lt;?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-
-$test = &amp;new GroupTest('All tests');
-$test-&gt;addTestFile('log_test.php');
-$test-&gt;run(new HtmlReporter());
-?&gt;</strong>
-</pre>
- The method <span class="new_code">GroupTest::addTestFile()</span>
- will include the test case file and read any new classes created
- that are descended from <span class="new_code">SimpleTestCase</span>, of which
- <span class="new_code">UnitTestCase</span> is one example.
- Just the class names are stored for now, so that the test runner
- can instantiate the class when it works its way
- through your test suite.
- </p>
- <p>
- For this to work properly the test case file should not blindly include
- any other test case extensions that do not actually run tests.
- This could result in extra test cases being counted during the test
- run.
- Hardly a major problem, but to avoid this inconvenience simply add
- a <span class="new_code">SimpleTestOptions::ignore()</span> directive
- somewhere in the test case file.
- Also the test case file should not have been included
- elsewhere or no cases will be added to this group test.
- This would be a more serious error as if the test case classes are
- already loaded by PHP the <span class="new_code">GroupTest::addTestFile()</span>
- method will not detect them.
- </p>
- <p>
- To display the results it is necessary only to invoke
- <em>tests/all_tests.php</em> from the web server.
- </p>
-
- <p>
-<a class="target" name="mock">
-<h2>Using mock objects</h2>
-</a>
-</p>
- <p>
- Let's move further into the future.
- </p>
- <p>
- Assume that our logging class is tested and completed.
- Assume also that we are testing another class that is
- required to write log messages, say a
- <span class="new_code">SessionPool</span>.
- We want to test a method that will probably end up looking
- like this...
-<pre>
-<strong>
-class SessionPool {
- ...
- function logIn($username) {
- ...
- $this-&gt;_log-&gt;message("User $username logged in.");
- ...
- }
- ...
-}
-</strong>
-</pre>
- In the spirit of reuse we are using our
- <span class="new_code">Log</span> class.
- A conventional test case might look like this...
-<pre>
-<strong>
-&lt;?php
-require_once('../classes/log.php');
-require_once('../classes/session_pool.php');
-
-class TestOfSessionLogging extends UnitTestCase {
-
- function setUp() {
- @unlink('/temp/test.log');
- }
-
- function tearDown() {
- @unlink('/temp/test.log');
- }
-
- function testLogInIsLogged() {
- $log = new Log('/temp/test.log');
- $session_pool = &amp;new SessionPool($log);
- $session_pool-&gt;logIn('fred');
- $messages = file('/temp/test.log');
- $this-&gt;assertEqual($messages[0], "User fred logged in.\n");
- }
-}
-?&gt;</strong>
-</pre>
- This test case design is not all bad, but it could be improved.
- We are spending time fiddling with log files which are
- not part of our test. Worse, we have created close ties
- with the <span class="new_code">Log</span> class and
- this test.
- What if we don't use files any more, but use ths
- <em>syslog</em> library instead?
- Did you notice the extra carriage return in the message?
- Was that added by the logger?
- What if it also added a time stamp or other data?
- </p>
- <p>
- The only part that we really want to test is that a particular
- message was sent to the logger.
- We reduce coupling if we can pass in a fake logging class
- that simply records the message calls for testing, but
- takes no action.
- It would have to look exactly like our original though.
- </p>
- <p>
- If the fake object doesn't write to a file then we save on deleting
- the file before and after each test. We could save even more
- test code if the fake object would kindly run the assertion for us.
- <p>
- </p>
- Too good to be true?
- Luckily we can create such an object easily...
-<pre>
-&lt;?php
-require_once('../classes/log.php');
-require_once('../classes/session_pool.php');<strong>
-Mock::generate('Log');</strong>
-
-class TestOfSessionLogging extends UnitTestCase {
-
- function testLogInIsLogged() {<strong>
- $log = &amp;new MockLog($this);
- $log-&gt;expectOnce('message', array('User fred logged in.'));</strong>
- $session_pool = &amp;new SessionPool($log);
- $session_pool-&gt;logIn('fred');<strong>
- $log-&gt;tally();</strong>
- }
-}
-?&gt;
-</pre>
- The <span class="new_code">tally()</span> call is needed to
- tell the mock object that time is up for the expected call
- count.
- Without it the mock would wait forever for the method
- call to come in without ever actually notifying the test case.
- The other test will be triggered when the call to
- <span class="new_code">message()</span> is invoked on the
- <span class="new_code">MockLog</span> object.
- The mock call will trigger a parameter comparison and then send the
- resulting pass or fail event to the test display.
- Wildcards can be included here too so as to prevent tests
- becoming too specific.
- </p>
- <p>
- The mock objects in the SimpleTest suite can have arbitrary
- return values set, sequences of returns, return values
- selected according to the incoming arguments, sequences of
- parameter expectations and limits on the number of times
- a method is to be invoked.
- </p>
- <p>
- For this test to run the mock objects library must have been
- included in the test suite, say in <em>all_tests.php</em>.
- </p>
-
- <p>
-<a class="target" name="web">
-<h2>Web page testing</h2>
-</a>
-</p>
- <p>
- One of the requirements of web sites is that they produce web
- pages.
- If you are building a project top-down and you want to fully
- integrate testing along the way then you will want a way of
- automatically navigating a site and examining output for
- correctness.
- This is the job of a web tester.
- </p>
- <p>
- The web testing in SimpleTest is fairly primitive, there is
- no JavaScript for example.
- To give an idea here is a trivial example where a home
- page is fetched, from which we navigate to an "about"
- page and then test some client determined content.
-<pre>
-&lt;?php<strong>
-require_once('simpletest/web_tester.php');</strong>
-require_once('simpletest/reporter.php');
-<strong>
-class TestOfAbout extends WebTestCase {
-
- function setUp() {
- $this-&gt;get('http://test-server/index.php');
- $this-&gt;clickLink('About');
- }
-
- function testSearchEngineOptimisations() {
- $this-&gt;assertTitle('A long title about us for search engines');
- $this-&gt;assertWantedPattern('/a popular keyphrase/i');
- }
-}</strong>
-$test = &amp;new TestOfAbout();
-$test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- With this code as an acceptance test you can ensure that
- the content always meets the specifications of both the
- developers and the other project stakeholders.
- </p>
- <p>
- <a href="http://sourceforge.net/projects/simpletest/"><img src="http://sourceforge.net/sflogo.php?group_id=76550&amp;type=5" width="210" height="62" border="0" alt="SourceForge.net Logo"></a>
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/mock_objects_documentation.html b/tests/UnitTests/simpletest/docs/en/mock_objects_documentation.html
deleted file mode 100644
index 126b58dd..00000000
--- a/tests/UnitTests/simpletest/docs/en/mock_objects_documentation.html
+++ /dev/null
@@ -1,713 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP mock objects documentation</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>
-<span class="chosen">Mock objects</span>
-</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>Mock objects documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="what">
-<h2>What are mock objects?</h2>
-</a>
-</p>
- <p>
- Mock objects have two roles during a test case: actor and critic.
- </p>
- <p>
- The actor behaviour is to simulate objects that are difficult to
- set up or time consuming to set up for a test.
- The classic example is a database connection.
- Setting up a test database at the start of each test would slow
- testing to a crawl and would require the installation of the
- database engine and test data on the test machine.
- If we can simulate the connection and return data of our
- choosing we not only win on the pragmatics of testing, but can
- also feed our code spurious data to see how it responds.
- We can simulate databases being down or other extremes
- without having to create a broken database for real.
- In other words, we get greater control of the test environment.
- </p>
- <p>
- If mock objects only behaved as actors they would simply be
- known as <a href="server_stubs_documentation.html">server stubs</a>.
- </p>
- <p>
- However, the mock objects not only play a part (by supplying chosen
- return values on demand) they are also sensitive to the
- messages sent to them (via expectations).
- By setting expected parameters for a method call they act
- as a guard that the calls upon them are made correctly.
- If expectations are not met they save us the effort of
- writing a failed test assertion by performing that duty on our
- behalf.
- In the case of an imaginary database connection they can
- test that the query, say SQL, was correctly formed by
- the object that is using the connection.
- Set them up with fairly tight expectations and you will
- hardly need manual assertions at all.
- </p>
-
- <p>
-<a class="target" name="creation">
-<h2>Creating mock objects</h2>
-</a>
-</p>
- <p>
- In the same way that we create server stubs, all we need is an
- existing class, say a database connection that looks like this...
-<pre>
-<strong>class DatabaseConnection {
- function DatabaseConnection() {
- }
-
- function query() {
- }
-
- function selectQuery() {
- }
-}</strong>
-</pre>
- The class does not need to have been implemented yet.
- To create a mock version of the class we need to include the
- mock object library and run the generator...
-<pre>
-<strong>require_once('simpletest/unit_tester.php');
-require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-
-Mock::generate('DatabaseConnection');</strong>
-</pre>
- This generates a clone class called
- <span class="new_code">MockDatabaseConnection</span>.
- We can now create instances of the new class within
- our test case...
-<pre>
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-
-Mock::generate('DatabaseConnection');
-<strong>
-class MyTestCase extends UnitTestCase {
-
- function testSomething() {
- $connection = &amp;new MockDatabaseConnection($this);
- }
-}</strong>
-</pre>
- Unlike the generated stubs the mock constructor needs a reference
- to the test case so that it can dispatch passes and failures while
- checking its expectations.
- This means that mock objects can only be used within test cases.
- Despite this their extra power means that stubs are hardly ever used
- if mocks are available.
- </p>
- <p>
- <a class="target" name="stub">
-<h2>Mocks as actors</h2>
-</a>
- </p>
- <p>
- The mock version of a class has all the methods of the original
- so that operations like
- <span class="new_code">$connection-&gt;query()</span> are still
- legal.
- As with stubs we can replace the default null return values...
-<pre>
-<strong>$connection-&gt;setReturnValue('query', 37);</strong>
-</pre>
- Now every time we call
- <span class="new_code">$connection-&gt;query()</span> we get
- the result of 37.
- As with the stubs we can set wildcards and we can overload the
- wildcard parameter.
- We can also add extra methods to the mock when generating it
- and choose our own class name...
-<pre>
-<strong>Mock::generate('DatabaseConnection', 'MyMockDatabaseConnection', array('setOptions'));</strong>
-</pre>
- Here the mock will behave as if the <span class="new_code">setOptions()</span>
- existed in the original class.
- This is handy if a class has used the PHP <span class="new_code">overload()</span>
- mechanism to add dynamic methods.
- You can create a special mock to simulate this situation.
- </p>
- <p>
- All of the patterns available with server stubs are available
- to mock objects...
-<pre>
-class Iterator {
- function Iterator() {
- }
-
- function next() {
- }
-}
-</pre>
- Again, assuming that this iterator only returns text until it
- reaches the end, when it returns false, we can simulate it
- with...
-<pre>
-Mock::generate('Iterator');
-
-class IteratorTest extends UnitTestCase() {
-
- function testASequence() {<strong>
- $iterator = &amp;new MockIterator($this);
- $iterator-&gt;setReturnValue('next', false);
- $iterator-&gt;setReturnValueAt(0, 'next', 'First string');
- $iterator-&gt;setReturnValueAt(1, 'next', 'Second string');</strong>
- ...
- }
-}
-</pre>
- When <span class="new_code">next()</span> is called on the
- mock iterator it will first return "First string",
- on the second call "Second string" will be returned
- and on any other call <span class="new_code">false</span> will
- be returned.
- The sequenced return values take precedence over the constant
- return value.
- The constant one is a kind of default if you like.
- </p>
- <p>
- A repeat of the stubbed information holder with name/value pairs...
-<pre>
-class Configuration {
- function Configuration() {
- }
-
- function getValue($key) {
- }
-}
-</pre>
- This is a classic situation for using mock objects as
- actual configuration will vary from machine to machine,
- hardly helping the reliability of our tests if we use it
- directly.
- The problem though is that all the data comes through the
- <span class="new_code">getValue()</span> method and yet
- we want different results for different keys.
- Luckily the mocks have a filter system...
-<pre>
-<strong>$config = &amp;new MockConfiguration($this);
-$config-&gt;setReturnValue('getValue', 'primary', array('db_host'));
-$config-&gt;setReturnValue('getValue', 'admin', array('db_user'));
-$config-&gt;setReturnValue('getValue', 'secret', array('db_password'));</strong>
-</pre>
- The extra parameter is a list of arguments to attempt
- to match.
- In this case we are trying to match only one argument which
- is the look up key.
- Now when the mock object has the
- <span class="new_code">getValue()</span> method invoked
- like this...
-<pre>
-$config-&gt;getValue('db_user')
-</pre>
- ...it will return "admin".
- It finds this by attempting to match the calling arguments
- to its list of returns one after another until
- a complete match is found.
- </p>
- <p>
- There are times when you want a specific object to be
- dished out by the mock rather than a copy.
- Again this is identical to the server stubs mechanism...
-<pre>
-class Thing {
-}
-
-class Vector {
- function Vector() {
- }
-
- function get($index) {
- }
-}
-</pre>
- In this case you can set a reference into the mock's
- return list...
-<pre>
-$thing = new Thing();<strong>
-$vector = &amp;new MockVector($this);
-$vector-&gt;setReturnReference('get', $thing, array(12));</strong>
-</pre>
- With this arrangement you know that every time
- <span class="new_code">$vector-&gt;get(12)</span> is
- called it will return the same
- <span class="new_code">$thing</span> each time.
- </p>
-
- <p>
-<a class="target" name="expectations">
-<h2>Mocks as critics</h2>
-</a>
-</p>
- <p>
- Although the server stubs approach insulates your tests from
- real world disruption, it is only half the benefit.
- You can have the class under test receiving the required
- messages, but is your new class sending correct ones?
- Testing this can get messy without a mock objects library.
- </p>
- <p>
- By way of example, suppose we have a
- <span class="new_code">SessionPool</span> class that we
- want to add logging to.
- Rather than grow the original class into something more
- complicated, we want to add this behaviour with a decorator (GOF).
- The <span class="new_code">SessionPool</span> code currently looks
- like this...
-<pre>
-<strong>class SessionPool {
- function SessionPool() {
- ...
- }
-
- function &amp;findSession($cookie) {
- ...
- }
- ...
-}
-
-class Session {
- ...
-}</strong>
-&lt;/php&gt;
- While our logging code looks like this...
-&lt;php&gt;<strong>
-class Log {
- function Log() {
- ...
- }
-
- function message() {
- ...
- }
-}
-
-class LoggingSessionPool {
- function LoggingSessionPool(&amp;$session_pool, &amp;$log) {
- ...
- }
-
- function &amp;findSession(\$cookie) {
- ...
- }
- ...
-}</strong>
-</pre>
- Out of all of this, the only class we want to test here
- is the <span class="new_code">LoggingSessionPool</span>.
- In particular we would like to check that the
- <span class="new_code">findSession()</span> method is
- called with the correct session ID in the cookie and that
- it sent the message "Starting session $cookie"
- to the logger.
- </p>
- <p>
- Despite the fact that we are testing only a few lines of
- production code, here is what we would have to do in a
- conventional test case:
- <ol>
- <li>Create a log object.</li>
- <li>Set a directory to place the log file.</li>
- <li>Set the directory permissions so we can write the log.</li>
- <li>Create a <span class="new_code">SessionPool</span> object.</li>
- <li>Hand start a session, which probably does lot's of things.</li>
- <li>Invoke <span class="new_code">findSession()</span>.</li>
- <li>Read the new Session ID (hope there is an accessor!).</li>
- <li>Raise a test assertion to confirm that the ID matches the cookie.</li>
- <li>Read the last line of the log file.</li>
- <li>Pattern match out the extra logging timestamps, etc.</li>
- <li>Assert that the session message is contained in the text.</li>
- </ol>
- It is hardly surprising that developers hate writing tests
- when they are this much drudgery.
- To make things worse, every time the logging format changes or
- the method of creating new sessions changes, we have to rewrite
- parts of this test even though this test does not officially
- test those parts of the system.
- We are creating headaches for the writers of these other classes.
- </p>
- <p>
- Instead, here is the complete test method using mock object magic...
-<pre>
-Mock::generate('Session');
-Mock::generate('SessionPool');
-Mock::generate('Log');
-
-class LoggingSessionPoolTest extends UnitTestCase {
- ...
- function testFindSessionLogging() {<strong>
- $session = &amp;new MockSession($this);
- $pool = &amp;new MockSessionPool($this);
- $pool-&gt;setReturnReference('findSession', $session);
- $pool-&gt;expectOnce('findSession', array('abc'));
-
- $log = &amp;new MockLog($this);
- $log-&gt;expectOnce('message', array('Starting session abc'));
-
- $logging_pool = &amp;new LoggingSessionPool($pool, $log);
- $this-&gt;assertReference($logging_pool-&gt;findSession('abc'), $session);
- $pool-&gt;tally();
- $log-&gt;tally();</strong>
- }
-}
-</pre>
- We start by creating a dummy session.
- We don't have to be too fussy about this as the check
- for which session we want is done elsewhere.
- We only need to check that it was the same one that came
- from the session pool.
- </p>
- <p>
- <span class="new_code">findSession()</span> is a factory
- method the simulation of which is described <a href="#stub">above</a>.
- The point of departure comes with the first
- <span class="new_code">expectOnce()</span> call.
- This line states that whenever
- <span class="new_code">findSession()</span> is invoked on the
- mock, it will test the incoming arguments.
- If it receives the single argument of a string "abc"
- then a test pass is sent to the unit tester, otherwise a fail is
- generated.
- This was the part where we checked that the right session was asked for.
- The argument list follows the same format as the one for setting
- return values.
- You can have wildcards and sequences and the order of
- evaluation is the same.
- </p>
- <p>
- If the call is never made then neither a pass nor a failure will
- generated.
- To get around this we must tell the mock when the test is over
- so that the object can decide if the expectation has been met.
- The unit tester assertion for this is triggered by the
- <span class="new_code">tally()</span> call at the end of
- the test.
- </p>
- <p>
- We use the same pattern to set up the mock logger.
- We tell it that it should have
- <span class="new_code">message()</span> invoked
- once only with the argument "Starting session abc".
- By testing the calling arguments, rather than the logger output,
- we insulate the test from any display changes in the logger.
- </p>
- <p>
- We start to run our tests when we create the new
- <span class="new_code">LoggingSessionPool</span> and feed
- it our preset mock objects.
- Everything is now under our control.
- Finally we confirm that the
- <span class="new_code">$session</span> we gave our decorator
- is the one that we get back and tell the mocks to run their
- internal call count tests with the
- <span class="new_code">tally()</span> calls.
- </p>
- <p>
- This is still quite a bit of test code, but the code is very
- strict.
- If it still seems rather daunting there is a lot less of it
- than if we tried this without mocks and this particular test,
- interactions rather than output, is always more work to set
- up.
- More often you will be testing more complex situations without
- needing this level or precision.
- Also some of this can be refactored into a test case
- <span class="new_code">setUp()</span> method.
- </p>
- <p>
- Here is the full list of expectations you can set on a mock object
- in <a href="http://www.lastcraft.com/simple_test.php">SimpleTest</a>...
- <table>
-<thead>
- <tr>
-<th>Expectation</th><th>Needs <span class="new_code">tally()</span></th>
-</tr>
- </thead>
-<tbody>
-<tr>
- <td><span class="new_code">expectArguments($method, $args)</span></td>
- <td style="text-align: center">No</td>
- </tr>
- <tr>
- <td><span class="new_code">expectArgumentsAt($timing, $method, $args)</span></td>
- <td style="text-align: center">No</td>
- </tr>
- <tr>
- <td><span class="new_code">expectCallCount($method, $count)</span></td>
- <td style="text-align: center">Yes</td>
- </tr>
- <tr>
- <td><span class="new_code">expectMaximumCallCount($method, $count)</span></td>
- <td style="text-align: center">No</td>
- </tr>
- <tr>
- <td><span class="new_code">expectMinimumCallCount($method, $count)</span></td>
- <td style="text-align: center">Yes</td>
- </tr>
- <tr>
- <td><span class="new_code">expectNever($method)</span></td>
- <td style="text-align: center">No</td>
- </tr>
- <tr>
- <td><span class="new_code">expectOnce($method, $args)</span></td>
- <td style="text-align: center">Yes</td>
- </tr>
- <tr>
- <td><span class="new_code">expectAtLeastOnce($method, $args)</span></td>
- <td style="text-align: center">Yes</td>
- </tr>
- </tbody>
-</table>
- Where the parameters are...
- <dl>
- <dt class="new_code">$method</dt>
- <dd>The method name, as a string, to apply the condition to.</dd>
- <dt class="new_code">$args</dt>
- <dd>
- The arguments as a list. Wildcards can be included in the same
- manner as for <span class="new_code">setReturn()</span>.
- This argument is optional for <span class="new_code">expectOnce()</span>
- and <span class="new_code">expectAtLeastOnce()</span>.
- </dd>
- <dt class="new_code">$timing</dt>
- <dd>
- The only point in time to test the condition.
- The first call starts at zero.
- </dd>
- <dt class="new_code">$count</dt>
- <dd>The number of calls expected.</dd>
- </dl>
- The method <span class="new_code">expectMaximumCallCount()</span>
- is slightly different in that it will only ever generate a failure.
- It is silent if the limit is never reached.
- </p>
- <p>
- Like the assertions within test cases, all of the expectations
- can take a message override as an extra parameter.
- Also the original failure message can be embedded in the output
- as "%s".
- </p>
-
- <p>
-<a class="target" name="approaches">
-<h2>Other approaches</h2>
-</a>
-</p>
- <p>
- There are three approaches to creating mocks including the one
- that SimpleTest employs.
- Coding them by hand using a base class, generating them to
- a file and dynamically generating them on the fly.
- </p>
- <p>
- Mock objects generated with <a href="simple_test.html">SimpleTest</a>
- are dynamic.
- They are created at run time in memory, using
- <span class="new_code">eval()</span>, rather than written
- out to a file.
- This makes the mocks easy to create, a one liner,
- especially compared with hand
- crafting them in a parallel class hierarchy.
- The problem is that the behaviour is usually set up in the tests
- themselves.
- If the original objects change the mock versions
- that the tests rely on can get out of sync.
- This can happen with the parallel hierarchy approach as well,
- but is far more quickly detected.
- </p>
- <p>
- The solution, of course, is to add some real integration
- tests.
- You don't need very many and the convenience gained
- from the mocks more than outweighs the small amount of
- extra testing.
- You cannot trust code that was only tested with mocks.
- </p>
- <p>
- If you are still determined to build static libraries of mocks
- because you want to simulate very specific behaviour, you can
- achieve the same effect using the SimpleTest class generator.
- In your library file, say <em>mocks/connection.php</em> for a
- database connection, create a mock and inherit to override
- special methods or add presets...
-<pre>
-&lt;?php
- require_once('simpletest/mock_objects.php');
- require_once('../classes/connection.php');
-<strong>
- Mock::generate('Connection', 'BasicMockConnection');
- class MockConnection extends BasicMockConnection {
- function MockConnection(&amp;$test, $wildcard = '*') {
- $this-&gt;BasicMockConnection($test, $wildcard);
- $this-&gt;setReturn('query', false);
- }
- }</strong>
-?&gt;
-</pre>
- The generate call tells the class generator to create
- a class called <span class="new_code">BasicMockConnection</span>
- rather than the usual <span class="new_code">MockConnection</span>.
- We then inherit from this to get our version of
- <span class="new_code">MockConnection</span>.
- By intercepting in this way we can add behaviour, here setting
- the default value of <span class="new_code">query()</span> to be false.
- By using the default name we make sure that the mock class
- generator will not recreate a different one when invoked elsewhere in the
- tests.
- It never creates a class if it already exists.
- As long as the above file is included first then all tests
- that generated <span class="new_code">MockConnection</span> should
- now be using our one instead.
- If we don't get the order right and the mock library
- creates one first then the class creation will simply fail.
- </p>
- <p>
- Use this trick if you find you have a lot of common mock behaviour
- or you are getting frequent integration problems at later
- stages of testing.
- </p>
-
- <p>
-<a class="target" name="other_testers">
-<h2>I think SimpleTest stinks!</h2>
-</a>
-</p>
- <p>
- But at the time of writing it is the only one with mock objects,
- so are you stuck with it?
- </p>
- <p>
- No, not at all.
- <a href="simple_test.html">SimpleTest</a> is a toolkit and one of those
- tools is the mock objects which can be employed independently.
- Suppose you have your own favourite unit tester and all your current
- test cases are written using it.
- Pretend that you have called your unit tester PHPUnit (everyone else has)
- and the core test class looks like this...
-<pre>
-class PHPUnit {
- function PHPUnit() {
- }
-
- function assertion($message, $assertion) {
- }
- ...
-}
-</pre>
- All the <span class="new_code">assertion()</span> method does
- is print some fancy output and the boolean assertion parameter determines
- whether to print a pass or a failure.
- Let's say that it is used like this...
-<pre>
-$unit_test = new PHPUnit();
-$unit_test&gt;assertion('I hope this file exists', file_exists('my_file'));
-</pre>
- How do you use mocks with this?
- </p>
- <p>
- There is a protected method on the base mock class
- <span class="new_code">SimpleMock</span> called
- <span class="new_code">_assertTrue()</span> and
- by overriding this method we can use our own assertion format.
- We start with a subclass, in say <em>my_mock.php</em>...
-<pre>
-<strong>&lt;?php
- require_once('simpletest/mock_objects.php');
-
- class MyMock extends SimpleMock() {
- function MyMock(&amp;$test, $wildcard) {
- $this-&gt;SimpleMock($test, $wildcard);
- }
-
- function _assertTrue($assertion, $message) {
- $test = &amp;$this-&gt;getTest();
- $test-&gt;assertion($message, $assertion);
- }
- }
-?&gt;</strong>
-</pre>
- Now instantiating <span class="new_code">MyMock</span> will create
- an object that speaks the same language as your tester.
- The catch is of course that we never create such an object, the
- code generator does.
- We need just one more line of code to tell the generator to use
- your mock instead...
-<pre>
-&lt;?php
- require_once('simpletst/mock_objects.php');
-
- class MyMock extends SimpleMock() {
- function MyMock($test, $wildcard) {
- $this-&gt;SimpleMock(&amp;$test, $wildcard);
- }
-
- function _assertTrue($assertion, $message , &amp;$test) {
- $test-&gt;assertion($message, $assertion);
- }
- }<strong>
- SimpleTestOptions::setMockBaseClass('MyMock');</strong>
-?&gt;
-</pre>
- From now on you just include <em>my_mock.php</em> instead of the
- default <em>mock_objects.php</em> version and you can introduce
- mock objects into your existing test suite.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/overview.html b/tests/UnitTests/simpletest/docs/en/overview.html
deleted file mode 100644
index 5047598d..00000000
--- a/tests/UnitTests/simpletest/docs/en/overview.html
+++ /dev/null
@@ -1,422 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>
- Overview and feature list for the SimpleTest PHP unit tester and web tester
- </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>
-<span class="chosen">Overview</span>
-</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>Overview of SimpleTest</h1>
-<div class="content">
- <p>
-<a class="target" name="summary">
-<h2>What is SimpleTest?</h2>
-</a>
-</p>
- <p>
- The heart of SimpleTest is a testing framework built around
- test case classes.
- These are written as extensions of base test case classes,
- each extended with methods that actually contain test code.
- Top level test scripts then invoke the <span class="new_code">run()</span>
- methods on every one of these test cases in order.
- Each test method is written to invoke various assertions that
- the developer expects to be true such as
- <span class="new_code">assertEqual()</span>.
- If the expectation is correct, then a successful result is dispatched to the
- observing test reporter, but any failure triggers an alert
- and a description of the mismatch.
- </p>
- <p>
- A <a href="unit_test_documentation.html">test case</a> looks like this...
-<pre>
-&lt;?php
-class <strong>MyTestCase</strong> extends UnitTestCase {
- <strong>
- function testLog() {
- $log = &amp;new Log('my.log');
- $log-&gt;message('Hello');
- $this-&gt;assertTrue(file_exists('my.log'));
- }</strong>
-}
-?&gt;
-</pre>
- </p>
- <p>
- These tools are designed for the developer.
- Tests are written in the PHP language itself more or less
- as the application itself is built.
- The advantage of using PHP itself as the testing language is that
- there are no new languages to learn, testing can start straight away,
- and the developer can test any part of the code.
- Basically, all parts that can be accessed by the application code can also be
- accessed by the test code if they are in the same language.
- </p>
- <p>
- The simplest type of test case is the
- <a href="unit_tester_documentation.html">UnitTestCase</a>.
- This class of test case includes standard tests for equality,
- references and pattern matching.
- All these test the typical expectations of what you would
- expect the result of a function or method to be.
- This is by far the most common type of test in the daily
- routine of development, making up about 95% of test cases.
- </p>
- <p>
- The top level task of a web application though is not to
- produce correct output from its methods and objects, but
- to generate web pages.
- The <a href="web_tester_documentation.html">WebTestCase</a> class tests web
- pages.
- It simulates a web browser requesting a page, complete with
- cookies, proxies, secure connections, authentication, forms, frames and most
- navigation elements.
- With this type of test case, the developer can assert that
- information is present in the page and that forms and
- sessions are handled correctly.
- </p>
- <p>
- A <a href="web_tester_documentation.html">WebTestCase</a> looks like this...
-<pre>
-&lt;?php
-class <strong>MySiteTest</strong> extends WebTestCase {
- <strong>
- function testHomePage() {
- $this-&gt;get('http://www.my-site.com/index.php');
- $this-&gt;assertTitle('My Home Page');
- $this-&gt;clickLink('Contact');
- $this-&gt;assertTitle('Contact me');
- $this-&gt;assertWantedPattern('/Email me at/');
- }</strong>
-}
-?&gt;
-</pre>
- </p>
-
- <p>
-<a class="target" name="features">
-<h2>Feature list</h2>
-</a>
-</p>
- <p>
- The following is a very rough outline of past and future features
- and their expected point of release.
- I am afraid it is liable to change without warning as meeting the
- milestones rather depends on time available.
- Green stuff has been coded, but not necessarily released yet.
- If you have a pressing need for a green but unreleased feature
- then you should check-out the code from sourceforge CVS directly.
- A released feature is marked as "Done".
- <table>
-<thead>
- <tr>
-<th>Feature</th><th>Description</th><th>Release</th>
-</tr>
- </thead>
-<tbody>
-<tr>
- <td>Unit test case</td>
- <td>Core test case class and assertions</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Html display</td>
- <td>Simplest possible display</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Autoloading of test cases</td>
- <td>
- Reading a file with test cases and loading them into a
- group test automatically
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Mock objects code generator</td>
- <td>
- Objects capable of simulating other objects removing
- test dependencies
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Server stubs</td>
- <td>
- Mocks without expectations to be used outside of test cases,
- e.g. for prototyping
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Integration of other unit testers</td>
- <td>
- The ability to read and simulate test cases from PHPUnit
- and PEAR::PhpUnit
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Web test case</td>
- <td>Basic pattern matching of fetched pages</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>HTML parsing of pages</td>
- <td>Allows link following and title tag matching</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Partial mocks</td>
- <td>
- Mocking parts of a class for testing less than a class
- or for complex simulations
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Web cookie handling</td>
- <td>Correct handling of cookies when fetching pages</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Following redirects</td>
- <td>Page fetching automatically follows 300 redirects</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Form parsing</td>
- <td>Ability to submit simple forms and read default form values</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Command line interface</td>
- <td>Test display without the need of a web browser</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Exposure of expectation classes</td>
- <td>Can create precise tests with mocks as well as test cases</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>XML output and parsing</td>
- <td>
- Allows multi host testing and the integration of acceptance
- testing extensions
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Command line test case</td>
- <td>Allows testing of utilities and file handling</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>PHP Documentor compatibility</td>
- <td>Fully generated class level documentation</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Browser interface</td>
- <td>
- Exposure of lower level web browser interface for more
- detailed test cases
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>HTTP authentication</td>
- <td>
- Fetching protected web pages with basic authentication
- only
- </td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Browser navigation buttons</td>
- <td>Back, forward and retry</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>SSL support</td>
- <td>Can connect to https: pages</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Proxy support</td>
- <td>Can connect via. common proxies</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Frames support</td>
- <td>Handling of frames in web test cases</td>
- <td style="color: green;">Done</td>
- </tr>
- <tr>
- <td>Improved display</td>
- <td>Better web GUI with tree display of test cases</td>
- <td style="color: red;">1.1</td>
- </tr>
- <tr>
- <td>Localisation</td>
- <td>Messages abstracted and code generated from XML</td>
- <td style="color: red;">1.1</td>
- </tr>
- <tr>
- <td>File upload testing</td>
- <td>Can simulate the input type file tag</td>
- <td style="color: red;">1.1</td>
- </tr>
- <tr>
- <td>Mocking interfaces</td>
- <td>Can generate mock objects to interfaces as well as classes</td>
- <td style="color: red;">2.0</td>
- </tr>
- <tr>
- <td>Testing exceptions</td>
- <td>Similar to testing PHP errors</td>
- <td style="color: red;">2.0</td>
- </tr>
- <tr>
- <td>XPath searching of elements</td>
- <td>Can make use of HTML tidy for faster and more flexible content matching</td>
- <td style="color: red;">2.0</td>
- </tr>
- </tbody>
-</table>
- PHP5 migraton will start straight after the version 1.1 series,
- whereupon PHP4 will no longer be supported.
- SimpleTest is currently compatible with PHP5, but will not
- make use of all of the new features until version 2.
- </p>
-
- <p>
-<a class="target" name="resources">
-<h2>Web resources for testing</h2>
-</a>
-</p>
- <p>
- Process is at least as important as tools.
- The type of process that makes the heaviest use of a developer's
- testing tool is of course
- <a href="http://www.extremeprogramming.org/">Extreme Programming</a>.
- This is one of the
- <a href="http://www.agilealliance.com/articles/index">Agile Methodologies</a>
- which combine various practices to "flatten the cost curve" of software development.
- More extreme still is <a href="http://www.testdriven.com/modules/news/">Test Driven Development</a>,
- where you very strictly adhere to the rule of no coding until you have a test.
- If you're more of a planner or believe that experience trumps evolution,
- you may prefer the
- <a href="http://www.therationaledge.com/content/dec_01/f_spiritOfTheRUP_pk.html">RUP</a> approach.
- I haven't tried it, but even I can see that you will need test tools (see figure 9).
- </p>
- <p>
- Most unit testers clone <a href="http://www.junit.org/">JUnit</a> to some degree,
- as far as the interface at least. There is a wealth of information on the
- JUnit site including the
- <a href="http://junit.sourceforge.net/doc/faq/faq.htm">FAQ</a>
- which contains plenty of general advice on testing.
- Once you get bitten by the bug you will certainly appreciate the phrase
- <a href="http://junit.sourceforge.net/doc/testinfected/testing.htm">test infected</a>
- coined by Eric Gamma.
- If you are still reviewing which unit tester to use the main choices
- are <a href="http://phpunit.sourceforge.net/">PHPUnit</a>
- and <a href="http://pear.php.net/manual/en/package.php.phpunit.php">Pear PHP::PHPUnit</a>.
- They currently lack a lot of features found in
- <a href="http://www.lastcraft.com/simple_test.php">SimpleTest</a>, but the PEAR
- version at least has been upgraded for PHP5 and is recommended if you are porting
- existing <a href="http://www.junit.org/">JUnit</a> test cases.
- </p>
- <p>
- Library writers don't seem to ship tests with their code very often
- which is a shame.
- Library code that includes tests can be more safely refactored and
- the test code can act as additional documentation in a fairly standard
- form.
- This can save trawling the source code for clues when problems occour,
- especially when upgrading such a library.
- Libraries using SimpleTest for their unit testing include
- <a href="http://wact.sourceforge.net/">WACT</a> and
- <a href="http://sourceforge.net/projects/htmlsax">PEAR::XML_HTMLSax</a>.
- </p>
- <p>
- There is currently a sad lack of material on mock objects, which is a shame
- as unit testing without them is a lot more work.
- The <a href="http://www.sidewize.com/company/mockobjects.pdf">original mock objects paper</a>
- is very Java focused, but still worth a read.
- As a new technology there are plenty of discussions and debate on how to use mocks,
- often on Wikis such as
- <a href="http://xpdeveloper.com/cgi-bin/oldwiki.cgi?MockObjects">Extreme Tuesday</a>
- or <a href="http://www.mockobjects.com/wiki/MocksObjectsPaper">www.mockobjects.com</a>
- or <a href="http://c2.com/cgi/wiki?MockObject">the original C2 Wiki</a>.
- Injecting mocks into a class is the main area of debate for which this
- <a href="http://www-106.ibm.com/developerworks/java/library/j-mocktest.html">paper on IBM</a>
- makes a good starting point.
- </p>
- <p>
- There are plenty of web testing tools, but most are written in Java and
- tutorials and advice are rather thin on the ground.
- The only hope is to look at the documentation for
- <a href="http://httpunit.sourceforge.net/">HTTPUnit</a>,
- <a href="http://htmlunit.sourceforge.net/">HTMLUnit</a>
- or <a href="http://jwebunit.sourceforge.net/">JWebUnit</a> and hope for clues.
- There are some XML driven test frameworks, but again most
- require Java to run.
- As SimpleTest does not support JavaScript you would probably
- have to look at these tools anyway if you have highly dynamic
- pages.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/partial_mocks_documentation.html b/tests/UnitTests/simpletest/docs/en/partial_mocks_documentation.html
deleted file mode 100644
index f4a6af00..00000000
--- a/tests/UnitTests/simpletest/docs/en/partial_mocks_documentation.html
+++ /dev/null
@@ -1,426 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP partial mocks documentation</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>
-<span class="chosen">Partial mocks</span>
-</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>Partial mock objects documentation</h1>
-<div class="content">
-
- <p>
- A partial mock is simply a pattern to alleviate a specific problem
- in testing with mock objects,
- that of getting mock objects into tight corners.
- It's quite a limited tool and possibly not even a good idea.
- It is included with SimpleTest because I have found it useful
- on more than one occasion and has saved a lot of work at that point.
- </p>
-
- <p>
-<a class="target" name="inject">
-<h2>The mock injection problem</h2>
-</a>
-</p>
- <p>
- When one object uses another it is very simple to just pass a mock
- version in already set up with its expectations.
- Things are rather tricker if one object creates another and the
- creator is the one you want to test.
- This means that the created object should be mocked, but we can
- hardly tell our class under test to create a mock instead.
- The tested class doesn't even know it is running inside a test
- after all.
- </p>
- <p>
- For example, suppose we are building a telnet client and it
- needs to create a network socket to pass its messages.
- The connection method might look something like...
-<pre>
-<strong>&lt;?php
- require_once('socket.php');
-
- class Telnet {
- ...
- function &amp;connect($ip, $port, $username, $password) {
- $socket = &amp;new Socket($ip, $port);
- $socket-&gt;read( ... );
- ...
- }
- }
-?&gt;</strong>
-</pre>
- We would really like to have a mock object version of the socket
- here, what can we do?
- </p>
- <p>
- The first solution is to pass the socket in as a parameter,
- forcing the creation up a level.
- Having the client handle this is actually a very good approach
- if you can manage it and should lead to factoring the creation from
- the doing.
- In fact, this is one way in which testing with mock objects actually
- forces you to code more tightly focused solutions.
- They improve your programming.
- </p>
- <p>
- Here this would be...
-<pre>
-&lt;?php
- require_once('socket.php');
-
- class Telnet {
- ...
- <strong>function &amp;connect(&amp;$socket, $username, $password) {
- $socket-&gt;read( ... );
- ...
- }</strong>
- }
-?&gt;
-</pre>
- This means that the test code is typical for a test involving
- mock objects.
-<pre>
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {<strong>
- $socket = &amp;new MockSocket($this);
- ...
- $telnet = &amp;new Telnet();
- $telnet-&gt;connect($socket, 'Me', 'Secret');
- ...</strong>
- }
-}
-</pre>
- It is pretty obvious though that one level is all you can go.
- You would hardly want your top level application creating
- every low level file, socket and database connection ever
- needed.
- It wouldn't know the constructor parameters anyway.
- </p>
- <p>
- The next simplest compromise is to have the created object passed
- in as an optional parameter...
-<pre>
-&lt;?php
- require_once('socket.php');
-
- class Telnet {
- ...<strong>
- function &amp;connect($ip, $port, $username, $password, $socket = false) {
- if (!$socket) {
- $socket = &amp;new Socket($ip, $port);
- }
- $socket-&gt;read( ... );</strong>
- ...
- return $socket;
- }
- }
-?&gt;
-</pre>
- For a quick solution this is usually good enough.
- The test now looks almost the same as if the parameter
- was formally passed...
-<pre>
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {<strong>
- $socket = &amp;new MockSocket($this);
- ...
- $telnet = &amp;new Telnet();
- $telnet-&gt;connect('127.0.0.1', 21, 'Me', 'Secret', &amp;$socket);
- ...</strong>
- }
-}
-</pre>
- The problem with this approach is its untidiness.
- There is test code in the main class and parameters passed
- in the test case that are never used.
- This is a quick and dirty approach, but nevertheless effective
- in most situations.
- </p>
- <p>
- The next method is to pass in a factory object to do the creation...
-<pre>
-&lt;?php
- require_once('socket.php');
-
- class Telnet {<strong>
- function Telnet(&amp;$network) {
- $this-&gt;_network = &amp;$network;
- }</strong>
- ...
- function &amp;connect($ip, $port, $username, $password) {<strong>
- $socket = &amp;$this-&gt;_network-&gt;createSocket($ip, $port);
- $socket-&gt;read( ... );</strong>
- ...
- return $socket;
- }
- }
-?&gt;
-</pre>
- This is probably the most highly factored answer as creation
- is now moved into a small specialist class.
- The networking factory can now be tested separately, but mocked
- easily when we are testing the telnet class...
-<pre>
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {<strong>
- $socket = &amp;new MockSocket($this);
- ...
- $network = &amp;new MockNetwork($this);
- $network-&gt;setReturnReference('createSocket', $socket);
- $telnet = &amp;new Telnet($network);
- $telnet-&gt;connect('127.0.0.1', 21, 'Me', 'Secret');
- ...</strong>
- }
-}
-</pre>
- The downside is that we are adding a lot more classes to the
- library.
- Also we are passing a lot of factories around which will
- make the code a little less intuitive.
- The most flexible solution, but the most complex.
- </p>
- <p>
- Is there a middle ground?
- </p>
-
- <p>
-<a class="target" name="creation">
-<h2>Protected factory method</h2>
-</a>
-</p>
- <p>
- There is a way we can circumvent the problem without creating
- any new application classes, but it involves creating a subclass
- when we do the actual testing.
- Firstly we move the socket creation into its own method...
-<pre>
-&lt;?php
- require_once('socket.php');
-
- class Telnet {
- ...
- function &amp;connect($ip, $port, $username, $password) {<strong>
- $socket = &amp;$this-&gt;_createSocket($ip, $port);</strong>
- $socket-&gt;read( ... );
- ...
- }<strong>
-
- function &amp;_createSocket($ip, $port) {
- return new Socket($ip, $port);
- }</strong>
- }
-?&gt;
-</pre>
- This is the only change we make to the application code.
- </p>
- <p>
- For the test case we have to create a subclass so that
- we can intercept the socket creation...
-<pre>
-<strong>class TelnetTestVersion extends Telnet {
- var $_mock;
-
- function TelnetTestVersion(&amp;$mock) {
- $this-&gt;_mock = &amp;$mock;
- $this-&gt;Telnet();
- }
-
- function &amp;_createSocket() {
- return $this-&gt;_mock;
- }
-}</strong>
-</pre>
- Here I have passed the mock in the constructor, but a
- setter would have done just as well.
- Note that the mock was set into the object variable
- before the constructor was chained.
- This is necessary in case the constructor calls
- <span class="new_code">connect()</span>.
- Otherwise it could get a null value from
- <span class="new_code">_createSocket()</span>.
- </p>
- <p>
- After the completion of all of this extra work the
- actual test case is fairly easy.
- We just test our new class instead...
-<pre>
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {<strong>
- $socket = &amp;new MockSocket($this);
- ...
- $telnet = &amp;new TelnetTestVersion($socket);
- $telnet-&gt;connect('127.0.0.1', 21, 'Me', 'Secret');
- ...</strong>
- }
-}
-</pre>
- The new class is very simple of course.
- It just sets up a return value, rather like a mock.
- It would be nice if it also checked the incoming parameters
- as well.
- Just like a mock.
- It seems we are likely to do this often, can
- we automate the subclass creation?
- </p>
-
- <p>
-<a class="target" name="partial">
-<h2>A partial mock</h2>
-</a>
-</p>
- <p>
- Of course the answer is "yes" or I would have stopped writing
- this by now!
- The previous test case was a lot of work, but we can
- generate the subclass using a similar approach to the mock objects.
- </p>
- <p>
- Here is the partial mock version of the test...
-<pre>
-<strong>Mock::generatePartial(
- 'Telnet',
- 'TelnetTestVersion',
- array('_createSocket'));</strong>
-
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {<strong>
- $socket = &amp;new MockSocket($this);
- ...
- $telnet = &amp;new TelnetTestVersion($this);
- $telnet-&gt;setReturnReference('_createSocket', $socket);
- $telnet-&gt;Telnet();
- $telnet-&gt;connect('127.0.0.1', 21, 'Me', 'Secret');
- ...</strong>
- }
-}
-</pre>
- The partial mock is a subclass of the original with
- selected methods "knocked out" with test
- versions.
- The <span class="new_code">generatePartial()</span> call
- takes three parameters: the class to be subclassed,
- the new test class name and a list of methods to mock.
- </p>
- <p>
- Instantiating the resulting objects is slightly tricky.
- The only constructor parameter of a partial mock is
- the unit tester reference.
- As with the normal mock objects this is needed for sending
- test results in response to checked expectations.
- </p>
- <p>
- The original constructor is not run yet.
- This is necessary in case the constructor is going to
- make use of the as yet unset mocked methods.
- We set any return values at this point and then run the
- constructor with its normal parameters.
- This three step construction of "new", followed
- by setting up the methods, followed by running the constructor
- proper is what distinguishes the partial mock code.
- </p>
- <p>
- Apart from construction, all of the mocked methods have
- the same features as mock objects and all of the unmocked
- methods behave as before.
- We can set expectations very easily...
-<pre>
-class TelnetTest extends UnitTestCase {
- ...
- function testConnection() {
- $socket = &amp;new MockSocket($this);
- ...
- $telnet = &amp;new TelnetTestVersion($this);
- $telnet-&gt;setReturnReference('_createSocket', $socket);<strong>
- $telnet-&gt;expectOnce('_createSocket', array('127.0.0.1', 21));</strong>
- $telnet-&gt;Telnet();
- $telnet-&gt;connect('127.0.0.1', 21, 'Me', 'Secret');
- ...<strong>
- $telnet-&gt;tally();</strong>
- }
-}
-</pre>
- </p>
-
- <p>
-<a class="target" name="less">
-<h2>Testing less than a class</h2>
-</a>
-</p>
- <p>
- The mocked out methods don't have to be factory methods,
- they could be any sort of method.
- In this way partial mocks allow us to take control of any part of
- a class except the constructor.
- We could even go as far as to mock every method
- except one we actually want to test.
- </p>
- <p>
- This last situation is all rather hypothetical, as I haven't
- tried it.
- I am open to the possibility, but a little worried that
- forcing object granularity may be better for the code quality.
- I personally use partial mocks as a way of overriding creation
- or for occasional testing of the TemplateMethod pattern.
- </p>
- <p>
- It's all going to come down to the coding standards of your
- project to decide which mechanism you use.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/reporter_documentation.html b/tests/UnitTests/simpletest/docs/en/reporter_documentation.html
deleted file mode 100644
index 2794c5ab..00000000
--- a/tests/UnitTests/simpletest/docs/en/reporter_documentation.html
+++ /dev/null
@@ -1,515 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP test runner and display documentation</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>
-<span class="chosen">Reporting</span>
-</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>Test reporter documentation</h1>
-<div class="content">
-
- <p>
- SimpleTest pretty much follows the MVC pattern
- (Model-View-Controller).
- The reporter classes are the view and the model is your
- test cases and their hiearchy.
- The controller is mostly hidden from the user of
- SimpleTest unless you want to change how the test cases
- are actually run, in which case it is possible to
- override the runner objects from within the test case.
- As usual with MVC, the controller is mostly undefined
- and there are other places to control the test run.
- </p>
-
- <p>
-<a class="target" name="html">
-<h2>Reporting results in HTML</h2>
-</a>
-</p>
- <p>
- The default test display is minimal in the extreme.
- It reports success and failure with the conventional red and
- green bars and shows a breadcrumb trail of test groups
- for every failed assertion.
- Here's a fail...
- <div class="demo">
- <h1>File test</h1>
- <span class="fail">Fail</span>: createnewfile-&gt;True assertion failed.<br>
- <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
- <strong>0</strong> passes, <strong>1</strong> fails and <strong>0</strong> exceptions.</div>
- </div>
- And here all tests passed...
- <div class="demo">
- <h1>File test</h1>
- <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
- <strong>1</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
- </div>
- The good news is that there are several points in the display
- hiearchy for subclassing.
- </p>
- <p>
- For web page based displays there is the
- <span class="new_code">HtmlReporter</span> class with the following
- signature...
-<pre>
-class HtmlReporter extends SimpleReporter {
- public HtmlReporter($encoding) { ... }
- public makeDry(boolean $is_dry) { ... }
- public void paintHeader(string $test_name) { ... }
- public void sendNoCacheHeaders() { ... }
- public void paintFooter(string $test_name) { ... }
- public void paintGroupStart(string $test_name, integer $size) { ... }
- public void paintGroupEnd(string $test_name) { ... }
- public void paintCaseStart(string $test_name) { ... }
- public void paintCaseEnd(string $test_name) { ... }
- public void paintMethodStart(string $test_name) { ... }
- public void paintMethodEnd(string $test_name) { ... }
- public void paintFail(string $message) { ... }
- public void paintPass(string $message) { ... }
- public void paintError(string $message) { ... }
- public void paintException(string $message) { ... }
- public void paintMessage(string $message) { ... }
- public void paintFormattedMessage(string $message) { ... }
- protected string _getCss() { ... }
- public array getTestList() { ... }
- public integer getPassCount() { ... }
- public integer getFailCount() { ... }
- public integer getExceptionCount() { ... }
- public integer getTestCaseCount() { ... }
- public integer getTestCaseProgress() { ... }
-}
-</pre>
- Here is what some of these methods mean. First the display methods
- that you will probably want to override...
- <ul class="api">
- <li>
- <span class="new_code">HtmlReporter(string $encoding)</span>
-<br>
- is the constructor.
- Note that the unit test sets up the link to the display
- rather than the other way around.
- The display is a mostly passive receiver of test events.
- This allows easy adaption of the display for other test
- systems beside unit tests, such as monitoring servers.
- The encoding is the character encoding you wish to
- display the test output in.
- In order to correctly render debug output when
- using the web tester, this should match the encoding
- of the site you are trying to test.
- The available character set strings are described in
- the PHP <a href="http://www.php.net/manual/en/function.htmlentities.php">html_entities()</a>
- function.
- </li>
- <li>
- <span class="new_code">void paintHeader(string $test_name)</span>
-<br>
- is called once at the very start of the test when the first
- start event arrives.
- The first start event is usually delivered by the top level group
- test and so this is where <span class="new_code">$test_name</span>
- comes from.
- It paints the page titles, CSS, body tag, etc.
- It returns nothing (<span class="new_code">void</span>).
- </li>
- <li>
- <span class="new_code">void paintFooter(string $test_name)</span>
-<br>
- Called at the very end of the test to close any tags opened
- by the page header.
- By default it also displays the red/green bar and the final
- count of results.
- Actually the end of the test happens when a test end event
- comes in with the same name as the one that started it all
- at the same level.
- The tests nest you see.
- Closing the last test finishes the display.
- </li>
- <li>
- <span class="new_code">void paintMethodStart(string $test_name)</span>
-<br>
- is called at the start of each test method.
- The name normally comes from method name.
- The other test start events behave the same way except
- that the group test one tells the reporter how large
- it is in number of held test cases.
- This is so that the reporter can display a progress bar
- as the runner churns through the test cases.
- </li>
- <li>
- <span class="new_code">void paintMethodEnd(string $test_name)</span>
-<br>
- backs out of the test started with the same name.
- </li>
- <li>
- <span class="new_code">void paintFail(string $message)</span>
-<br>
- paints a failure.
- By default it just displays the word fail, a breadcrumbs trail
- showing the current test nesting and the message issued by
- the assertion.
- </li>
- <li>
- <span class="new_code">void paintPass(string $message)</span>
-<br>
- by default does nothing.
- </li>
- <li>
- <span class="new_code">string _getCss()</span>
-<br>
- Returns the CSS styles as a string for the page header
- method.
- Additional styles have to be appended here if you are
- not overriding the page header.
- You will want to use this method in an overriden page header
- if you want to include the original CSS.
- </li>
- </ul>
- There are also some accessors to get information on the current
- state of the test suite.
- Use these to enrich the display...
- <ul class="api">
- <li>
- <span class="new_code">array getTestList()</span>
-<br>
- is the first convenience method for subclasses.
- Lists the current nesting of the tests as a list
- of test names.
- The first, most deeply nested test, is first in the
- list and the current test method will be last.
- </li>
- <li>
- <span class="new_code">integer getPassCount()</span>
-<br>
- returns the number of passes chalked up so far.
- Needed for the display at the end.
- </li>
- <li>
- <span class="new_code">integer getFailCount()</span>
-<br>
- is likewise the number of fails so far.
- </li>
- <li>
- <span class="new_code">integer getExceptionCount()</span>
-<br>
- is likewise the number of errors so far.
- </li>
- <li>
- <span class="new_code">integer getTestCaseCount()</span>
-<br>
- is the total number of test cases in the test run.
- This includes the grouping tests themselves.
- </li>
- <li>
- <span class="new_code">integer getTestCaseProgress()</span>
-<br>
- is the number of test cases completed so far.
- </li>
- </ul>
- One simple modification is to get the HtmlReporter to display
- the passes as well as the failures and errors...
-<pre>
-<strong>class ShowPasses extends HtmlReporter {
-
- function paintPass($message) {
- parent::paintPass($message);
- print "&amp;&lt;span class=\"pass\"&gt;Pass&lt;/span&gt;: ";
- $breadcrumb = $this-&gt;getTestList();
- array_shift($breadcrumb);
- print implode("-&amp;gt;", $breadcrumb);
- print "-&amp;gt;$message&lt;br /&gt;\n";
- }
-
- function _getCss() {
- return parent::_getCss() . ' .pass { color: green; }';
- }
-}</strong>
-</pre>
- </p>
- <p>
- One method that was glossed over was the <span class="new_code">makeDry()</span>
- method.
- If you run this method, with no parameters, on the reporter
- before the test suite is run no actual test methods
- will be called.
- You will still get the events of entering and leaving the
- test methods and test cases, but no passes or failures etc,
- because the test code will not actually be executed.
- </p>
- <p>
- The reason for this is to allow for more sophistcated
- GUI displays that allow the selection of individual test
- cases.
- In order to build a list of possible tests they need a
- report on the test structure for drawing, say a tree view
- of the test suite.
- With a reporter set to dry run that just sends drawing events
- this is easily accomplished.
- </p>
-
- <p>
-<a class="target" name="other">
-<h2>Extending the reporter</h2>
-</a>
-</p>
- <p>
- Rather than simply modifying the existing display, you might want to
- produce a whole new HTML look, or even generate text or XML.
- Rather than override every method in
- <span class="new_code">HtmlReporter</span> we can take one
- step up the class hiearchy to <span class="new_code">SimpleReporter</span>
- in the <em>simple_test.php</em> source file.
- </p>
- <p>
- A do nothing display, a blank canvas for your own creation, would
- be...
-<pre>
-<strong>require_once('simpletest/simple_test.php');</strong>
-
-class MyDisplay extends SimpleReporter {<strong>
- </strong>
- function paintHeader($test_name) {
- }
-
- function paintFooter($test_name) {
- }
-
- function paintStart($test_name, $size) {<strong>
- parent::paintStart($test_name, $size);</strong>
- }
-
- function paintEnd($test_name, $size) {<strong>
- parent::paintEnd($test_name, $size);</strong>
- }
-
- function paintPass($message) {<strong>
- parent::paintPass($message);</strong>
- }
-
- function paintFail($message) {<strong>
- parent::paintFail($message);</strong>
- }
-}
-</pre>
- No output would come from this class until you add it.
- </p>
-
- <p>
-<a class="target" name="cli">
-<h2>The command line reporter</h2>
-</a>
-</p>
- <p>
- SimpleTest also ships with a minimal command line reporter.
- The interface mimics JUnit to some extent, but paints the
- failure messages as they arrive.
- To use the command line reporter simply substitute it
- for the HTML version...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
-
- $test = &amp;new GroupTest('File test');
- $test-&gt;addTestFile('tests/file_test.php');
- $test-&gt;run(<strong>new TextReporter()</strong>);
-?&gt;
-</pre>
- Then invoke the test suite from the command line...
-<pre class="shell">
-php file_test.php
-</pre>
- You will need the command line version of PHP installed
- of course.
- A passing test suite looks like this...
-<pre class="shell">
-File test
-OK
-Test cases run: 1/1, Failures: 0, Exceptions: 0
-</pre>
- A failure triggers a display like this...
-<pre class="shell">
-File test
-1) True assertion failed.
- in createnewfile
-FAILURES!!!
-Test cases run: 1/1, Failures: 1, Exceptions: 0
-</pre>
- </p>
- <p>
- One of the main reasons for using a command line driven
- test suite is of using the tester as part of some automated
- process.
- To function properly in shell scripts the test script should
- return a non-zero exit code on failure.
- If a test suite fails the value <span class="new_code">false</span>
- is returned from the <span class="new_code">SimpleTest::run()</span>
- method.
- We can use that result to exit the script with the desired return
- code...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
-
- $test = &amp;new GroupTest('File test');
- $test-&gt;addTestFile('tests/file_test.php');
- <strong>exit ($test-&gt;run(new TextReporter()) ? 0 : 1);</strong>
-?&gt;
-</pre>
- Of course we don't really want to create two test scripts,
- a command line one and a web browser one, for each test suite.
- The command line reporter includes a method to sniff out the
- run time environment...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');
- require_once('simpletest/reporter.php');
-
- $test = &amp;new GroupTest('File test');
- $test-&gt;addTestFile('tests/file_test.php');
- <strong>if (TextReporter::inCli()) {</strong>
- exit ($test-&gt;run(new TextReporter()) ? 0 : 1);
- <strong>}</strong>
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- This is the form used within SimpleTest itself.
- </p>
-
- <p>
-<a class="target" name="xml">
-<h2>Remote testing</h2>
-</a>
-</p>
- <p>
- SimpleTest ships with an <span class="new_code">XmlReporter</span> class
- used for internal communication.
- When run the output looks like...
-<pre class="shell">
-&lt;?xml version="1.0"?&gt;
-&lt;run&gt;
- &lt;group size="4"&gt;
- &lt;name&gt;Remote tests&lt;/name&gt;
- &lt;group size="4"&gt;
- &lt;name&gt;Visual test with 48 passes, 48 fails and 4 exceptions&lt;/name&gt;
- &lt;case&gt;
- &lt;name&gt;testofunittestcaseoutput&lt;/name&gt;
- &lt;test&gt;
- &lt;name&gt;testofresults&lt;/name&gt;
- &lt;pass&gt;This assertion passed&lt;/pass&gt;
- &lt;fail&gt;This assertion failed&lt;/fail&gt;
- &lt;/test&gt;
- &lt;test&gt;
- ...
- &lt;/test&gt;
- &lt;/case&gt;
- &lt;/group&gt;
- &lt;/group&gt;
-&lt;/run&gt;
-</pre>
- You can make use of this format with the parser
- supplied as part of SimpleTest itself.
- This is called <span class="new_code">SimpleTestXmlParser</span> and
- resides in <em>xml.php</em> within the SimpleTest package...
-<pre>
-&lt;?php
- require_once('simpletest/xml.php');
-
- ...
- $parser = &amp;new SimpleTestXmlParser(new HtmlReporter());
- $parser-&gt;parse($test_output);
-?&gt;
-</pre>
- The <span class="new_code">$test_output</span> should be the XML format
- from the XML reporter, and could come from say a command
- line run of a test case.
- The parser sends events to the reporter just like any
- other test run.
- There are some odd occasions where this is actually useful.
- </p>
- <p>
- A problem with large test suites is thet they can exhaust
- the default 8Mb memory limit on a PHP process.
- By having the test groups output in XML and run in
- separate processes, the output can be reparsed to
- aggregate the results into a much smaller footprint top level
- test.
- </p>
- <p>
- Because the XML output can come from anywhere, this opens
- up the possibility of aggregating test runs from remote
- servers.
- A test case already exists to do this within the SimpleTest
- framework, but it is currently experimental...
-<pre>
-&lt;?php
- <strong>require_once('../remote.php');</strong>
- require_once('../reporter.php');
-
- $test_url = ...;
- $dry_url = ...;
-
- $test = &amp;new GroupTest('Remote tests');
- $test-&gt;addTestCase(<strong>new RemoteTestCase($test_url, $dry_url)</strong>);
- $test-&gt;run(new HtmlReporter());
-?&gt;
-</pre>
- The <span class="new_code">RemoteTestCase</span> takes the actual location
- of the test runner, basically a web page in XML format.
- It also takes the URL of a reporter set to do a dry run.
- This is so that progress can be reported upward correctly.
- The <span class="new_code">RemoteTestCase</span> can be added to test suites
- just like any other group test.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/server_stubs_documentation.html b/tests/UnitTests/simpletest/docs/en/server_stubs_documentation.html
deleted file mode 100644
index 445ba63e..00000000
--- a/tests/UnitTests/simpletest/docs/en/server_stubs_documentation.html
+++ /dev/null
@@ -1,388 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP server stubs documentation</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>
-<span class="chosen">Server stubs</span>
-</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>Server stubs documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="what">
-<h2>What are server stubs?</h2>
-</a>
-</p>
- <p>
- This was originally a pattern named by Robert Binder (Testing
- object-oriented systems: models, patterns, and tools,
- Addison-Wesley) in 1999.
- A server stub is a simulation of an object or component.
- It should exactly replace a component in a system for test
- or prototyping purposes, but remain lightweight.
- This allows tests to run more quickly, or if the simulated
- class has not been written, to run at all.
- </p>
-
- <p>
-<a class="target" name="creation">
-<h2>Creating server stubs</h2>
-</a>
-</p>
- <p>
- All we need is an existing class, say a database connection
- that looks like this...
-<pre>
-<strong>class DatabaseConnection {
- function DatabaseConnection() {
- }
-
- function query() {
- }
-
- function selectQuery() {
- }
-}</strong>
-</pre>
- The class does not need to have been implemented yet.
- To create a stub version of the class we need to include the
- server stub library and run the generator...
-<pre>
-<strong>require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-Stub::generate('DatabaseConnection');</strong>
-</pre>
- This generates a clone class called
- <span class="new_code">StubDatabaseConnection</span>.
- We can now create instances of the new class within
- our prototype script...
-<pre>
-require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-Stub::generate('DatabaseConnection');
-<strong>
-$connection = new StubDatabaseConnection();
-</strong>
-</pre>
- The stub version of a class has all the methods of the original
- so that operations like
- <span class="new_code">$connection-&gt;query()</span> are still
- legal.
- The return value will be <span class="new_code">null</span>,
- but we can change that with...
-<pre>
-<strong>$connection-&gt;setReturnValue('query', 37)</strong>
-</pre>
- Now every time we call
- <span class="new_code">$connection-&gt;query()</span> we get
- the result of 37.
- We can set the return value to anything, say a hash of
- imaginary database results or a list of persistent objects.
- Parameters are irrelevant here, we always get the same
- values back each time once they have been set up this way.
- That may not sound like a convincing replica of a
- database connection, but for the half a dozen lines of
- a test method it is usually all you need.
- </p>
-
- <p>
-<a class="target" name="patterns">
-<h2>Simulation patterns</h2>
-</a>
-</p>
- <p>
- Things aren't always that simple though.
- One common problem is iterators, where constantly returning
- the same value could cause an endless loop in the object
- being tested.
- For these we need to set up sequences of values.
- Let's say we have a simple iterator that looks like this...
-<pre>
-class Iterator {
- function Iterator() {
- }
-
- function next() {
- }
-}
-</pre>
- This is about the simplest iterator you could have.
- Assuming that this iterator only returns text until it
- reaches the end, when it returns false, we can simulate it
- with...
-<pre>
-<strong>Stub::generate('Iterator');
-
-$iterator = new StubIterator();
-$iterator-&gt;setReturnValue('next', false);
-$iterator-&gt;setReturnValueAt(0, 'next', 'First string');
-$iterator-&gt;setReturnValueAt(1, 'next', 'Second string');</strong>
-</pre>
- When <span class="new_code">next()</span> is called on the
- stub iterator it will first return "First string",
- on the second call "Second string" will be returned
- and on any other call <span class="new_code">false</span> will
- be returned.
- The sequenced return values take precedence over the constant
- return value.
- The constant one is a kind of default if you like.
- </p>
- <p>
- Another tricky situation is an overloaded
- <span class="new_code">get()</span> operation.
- An example of this is an information holder with name/value pairs.
- Say we have a configuration class like...
-<pre>
-class Configuration {
- function Configuration() {
- }
-
- function getValue($key) {
- }
-}
-</pre>
- This is a classic situation for using stub objects as
- actual configuration will vary from machine to machine,
- hardly helping the reliability of our tests if we use it
- directly.
- The problem though is that all the data comes through the
- <span class="new_code">getValue()</span> method and yet
- we want different results for different keys.
- Luckily the stubs have a filter system...
-<pre>
-<strong>Stub::generate('Configuration');
-
-$config = &amp;new StubConfiguration();
-$config-&gt;setReturnValue('getValue', 'primary', array('db_host'));
-$config-&gt;setReturnValue('getValue', 'admin', array('db_user'));
-$config-&gt;setReturnValue('getValue', 'secret', array('db_password'));</strong>
-</pre>
- The extra parameter is a list of arguments to attempt
- to match.
- In this case we are trying to match only one argument which
- is the look up key.
- Now when the server stub has the
- <span class="new_code">getValue()</span> method invoked
- like this...
-<pre>
-$config-&gt;getValue('db_user');
-</pre>
- ...it will return "admin".
- It finds this by attempting to match the calling arguments
- to its list of returns one after another until
- a complete match is found.
- </p>
- <p>
- You can set a default argument argument like so...
-<pre>
-<strong>
-$config-&gt;setReturnValue('getValue', false, array('*'));</strong>
-</pre>
- This is not the same as setting the return value without
- any argument requirements like this...
-<pre>
-<strong>
-$config-&gt;setReturnValue('getValue', false);</strong>
-</pre>
- In the first case it will accept any single argument,
- but exactly one is required.
- In the second case any number of arguments will do and
- it acts as a catchall after all other matches.
- Note that if we add further single parameter options after
- the wildcard in the first case, they will be ignored as the wildcard
- will match first.
- With complex parameter lists the ordering could be important
- or else desired matches could be masked by earlier wildcard
- ones.
- Declare the most specific matches first if you are not sure.
- </p>
- <p>
- There are times when you want a specific object to be
- dished out by the stub rather than just a copy.
- The PHP copy semantics force us to use a different method
- for this.
- You might be simulating a container for example...
-<pre>
-class Thing {
-}
-
-class Vector {
- function Vector() {
- }
-
- function get($index) {
- }
-}
-</pre>
- In this case you can set a reference into the stub's
- return list...
-<pre>
-Stub::generate('Vector');
-
-$thing = new Thing();<strong>
-$vector = &amp;new StubVector();
-$vector-&gt;setReturnReference('get', $thing, array(12));</strong>
-</pre>
- With this arrangement you know that every time
- <span class="new_code">$vector-&gt;get(12)</span> is
- called it will return the same
- <span class="new_code">$thing</span> each time.
- </p>
- <p>
- These three factors, timing, parameters and whether to copy,
- can be combined orthogonally.
- For example...
-<pre>
-$complex = &amp;new StubComplexThing();
-$stuff = new Stuff();<strong>
-$complex-&gt;setReturnReferenceAt(3, 'get', $stuff, array('*', 1));</strong>
-</pre>
- This will return the <span class="new_code">$stuff</span> only on the third
- call and only if two parameters were set the second of
- which must be the integer 1.
- That should cover most simple prototyping situations.
- </p>
- <p>
- A final tricky case is one object creating another, known
- as a factory pattern.
- Suppose that on a successful query to our imaginary
- database, a result set is returned as an iterator with
- each call to <span class="new_code">next()</span> giving
- one row until false.
- This sounds like a simulation nightmare, but in fact it can all
- be stubbed using the mechanics above.
- </p>
- <p>
- Here's how...
-<pre>
-Stub::generate('DatabaseConnection');
-Stub::generate('ResultIterator');
-
-class DatabaseTest extends UnitTestCase {
-
- function testUserFinder() {<strong>
- $result = &amp;new StubResultIterator();
- $result-&gt;setReturnValue('next', false);
- $result-&gt;setReturnValueAt(0, 'next', array(1, 'tom'));
- $result-&gt;setReturnValueAt(1, 'next', array(3, 'dick'));
- $result-&gt;setReturnValueAt(2, 'next', array(6, 'harry'));
-
- $connection = &amp;new StubDatabaseConnection();
- $connection-&gt;setReturnValue('query', false);
- $connection-&gt;setReturnReference(
- 'query',
- $result,
- array('select id, name from users'));</strong>
-
- $finder = &amp;new UserFinder($connection);
- $this-&gt;assertIdentical(
- $finder-&gt;findNames(),
- array('tom', 'dick', 'harry'));
- }
-}
-</pre>
- Now only if our
- <span class="new_code">$connection</span> is called with the correct
- <span class="new_code">query()</span> will the
- <span class="new_code">$result</span> be returned that is
- itself exhausted after the third call to <span class="new_code">next()</span>.
- This should be enough
- information for our <span class="new_code">UserFinder</span> class,
- the class actually
- being tested here, to come up with goods.
- A very precise test and not a real database in sight.
- </p>
-
- <p>
-<a class="target" name="options">
-<h2>Stub creation options</h2>
-</a>
-</p>
- <p>
- There are some additional options when creating stubs.
- At the generation stage we can change the class name...
-<pre>
-<strong>Stub::generate('Iterator', 'MyStubIterator');
-$iterator = &amp;new MyStubIterator();
-</strong>
-</pre>
- This is not very useful in itself as there would be no difference
- in this class and the default except for the name.
- However we can also add additional methods not found in the
- original interface...
-<pre>
-class Iterator {
-}
-<strong>Stub::generate('Iterator', 'PrototypeIterator', array('next', 'isError'));
-$iterator = &amp;new PrototypeIterator();
-$iterator-&gt;setReturnValue('next', 0);
-</strong>
-</pre>
- The <span class="new_code">next()</span> and
- <span class="new_code">isError()</span> methods can now have
- return values set just as if they existed in the original class.
- </p>
- <p>
- One other esoteric way of customising the stubs is to change
- the default wildcard used for parameter matching.
-<pre>
-<strong>Stub::generate('Connection');
-$iterator = &amp;new StubConnection('wild');
-$iterator-&gt;setReturnValue('query', array('id' =&gt; 33), array('wild'));
-</strong>
-</pre>
- The only reason to do this is if you genuinely wanted to test
- against the literal string "*" and didn't want it
- interpreted as "any".
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/unit_test_documentation.html b/tests/UnitTests/simpletest/docs/en/unit_test_documentation.html
deleted file mode 100644
index ddc2f0f0..00000000
--- a/tests/UnitTests/simpletest/docs/en/unit_test_documentation.html
+++ /dev/null
@@ -1,387 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>SimpleTest for PHP regression test documentation</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>
-<span class="chosen">Unit tester</span>
-</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>PHP Unit Test documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="unit">
-<h2>Unit test cases</h2>
-</a>
-</p>
- <p>
- The core system is a regression testing framework built around
- test cases.
- A sample test case looks like this...
-<pre>
-<strong>class FileTestCase extends UnitTestCase {
-}</strong>
-</pre>
- If no test name is supplied when chaining the constructor then
- the class name will be taken instead.
- This will be the name displayed in the test results.
- </p>
- <p>
- Actual tests are added as methods in the test case whose names
- by default start with the string "test" and
- when the test case is invoked all such methods are run in
- the order that PHP introspection finds them.
- As many test methods can be added as needed.
- For example...
-<pre>
-require_once('../classes/writer.php');
-
-class FileTestCase extends UnitTestCase {
- function FileTestCase() {
- $this-&gt;UnitTestCase('File test');
- }<strong>
-
- function setUp() {
- @unlink('../temp/test.txt');
- }
-
- function tearDown() {
- @unlink('../temp/test.txt');
- }
-
- function testCreation() {
- $writer = &amp;new FileWriter('../temp/test.txt');
- $writer-&gt;write('Hello');
- $this-&gt;assertTrue(file_exists('../temp/test.txt'), 'File created');
- }</strong>
-}
-</pre>
- The constructor is optional and usually omitted.
- Without a name, the class name is taken as the name of the test case.
- </p>
- <p>
- Our only test method at the moment is <span class="new_code">testCreation()</span>
- where we check that a file has been created by our
- <span class="new_code">Writer</span> object.
- We could have put the <span class="new_code">unlink()</span>
- code into this method as well, but by placing it in
- <span class="new_code">setUp()</span> and
- <span class="new_code">tearDown()</span> we can use it with
- other test methods that we add.
- </p>
- <p>
- The <span class="new_code">setUp()</span> method is run
- just before each and every test method.
- <span class="new_code">tearDown()</span> is run just after
- each and every test method.
- </p>
- <p>
- You can place some test case set up into the constructor to
- be run once for all the methods in the test case, but
- you risk test inteference that way.
- This way is slightly slower, but it is safer.
- Note that if you come from a JUnit background this will not
- be the behaviour you are used to.
- JUnit surprisingly reinstantiates the test case for each test
- method to prevent such interference.
- SimpleTest requires the end user to use <span class="new_code">setUp()</span>, but
- supplies additional hooks for library writers.
- </p>
- <p>
- The means of reporting test results (see below) are by a
- visiting display class
- that is notified by various <span class="new_code">assert...()</span>
- methods.
- Here is the full list for the <span class="new_code">UnitTestCase</span>
- class, the default for SimpleTest...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">assertTrue($x)</span></td><td>Fail if $x is false</td>
-</tr>
- <tr>
-<td><span class="new_code">assertFalse($x)</span></td><td>Fail if $x is true</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNull($x)</span></td><td>Fail if $x is set</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNotNull($x)</span></td><td>Fail if $x not set</td>
-</tr>
- <tr>
-<td><span class="new_code">assertIsA($x, $t)</span></td><td>Fail if $x is not the class or type $t</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNotA($x, $t)</span></td><td>Fail if $x is of the class or type $t</td>
-</tr>
- <tr>
-<td><span class="new_code">assertEqual($x, $y)</span></td><td>Fail if $x == $y is false</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNotEqual($x, $y)</span></td><td>Fail if $x == $y is true</td>
-</tr>
- <tr>
-<td><span class="new_code">assertIdentical($x, $y)</span></td><td>Fail if $x == $y is false or a type mismatch</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNotIdentical($x, $y)</span></td><td>Fail if $x == $y is true and types match</td>
-</tr>
- <tr>
-<td><span class="new_code">assertReference($x, $y)</span></td><td>Fail unless $x and $y are the same variable</td>
-</tr>
- <tr>
-<td><span class="new_code">assertCopy($x, $y)</span></td><td>Fail if $x and $y are the same variable</td>
-</tr>
- <tr>
-<td><span class="new_code">assertWantedPattern($p, $x)</span></td><td>Fail unless the regex $p matches $x</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoUnwantedPattern($p, $x)</span></td><td>Fail if the regex $p matches $x</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoErrors()</span></td><td>Fail if any PHP error occoured</td>
-</tr>
- <tr>
-<td><span class="new_code">assertError($x)</span></td><td>Fail if no PHP error or incorrect message</td>
-</tr>
- <tr>
-<td><span class="new_code">assertErrorPattern($p)</span></td><td>Fail unless the error matches the regex $p</td>
-</tr>
- </tbody>
-</table>
- All assertion methods can take an optional description to
- label the displayed result with.
- If omitted a default message is sent instead which is usually
- sufficient.
- This default message can still be embedded in your own message
- if you include "%s" within the string.
- All the assertions return true on a pass or false on failure.
- </p>
- <p>
- Some examples...
-<pre>
-<strong>$variable = null;
-$this-&gt;assertNull($variable, 'Should be cleared');</strong>
-</pre>
- ...will pass and normally show no message.
- If you have
- <a href="http://www.lastcraft.com/display_subclass_tutorial.php">set up the tester to display passes</a>
- as well then the message will be displayed as is.
-<pre>
-<strong>$this-&gt;assertIdentical(0, false, 'Zero is not false [%s]');</strong>
-</pre>
- This will fail as it performs a type
- check as well as a comparison between the two values.
- The "%s" part is replaced by the default
- error message that would have been shown if we had not
- supplied our own.
- This also allows us to nest test messages.
-<pre>
-<strong>$a = 1;
-$b = $a;
-$this-&gt;assertReference($a, $b);</strong>
-</pre>
- Will fail as the variable <span class="new_code">$a</span> is a copy of <span class="new_code">$b</span>.
-<pre>
-<strong>$this-&gt;assertWantedPattern('/hello/i', 'Hello world');</strong>
-</pre>
- This will pass as using a case insensitive match the string
- <span class="new_code">hello</span> is contained in <span class="new_code">Hello world</span>.
-<pre>
-<strong>trigger_error('Disaster');
-trigger_error('Catastrophe');
-$this-&gt;assertError();
-$this-&gt;assertError('Catastrophe');
-$this-&gt;assertNoErrors();</strong>
-</pre>
- This one takes some explanation as in fact they all pass!
- </p>
- <p>
- PHP errors in SimpleTest are trapped and placed in a queue.
- Here the first error check catches the "Disaster"
- message without checking the text and passes.
- This removes the error from the queue.
- The next error check tests not only the existence of the error,
- but also the text which here matches so another pass.
- With the queue now empty the last test will pass as well.
- If any unchecked errors are left at the end of a test method then
- an exception will be reported in the test.
- Note that SimpleTest cannot catch compile time PHP errors.
- </p>
- <p>
- The test cases also have some convenience methods for debugging
- code or extending the suite...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">setUp()</span></td><td>Runs this before each test method</td>
-</tr>
- <tr>
-<td><span class="new_code">tearDown()</span></td><td>Runs this after each test method</td>
-</tr>
- <tr>
-<td><span class="new_code">pass()</span></td><td>Sends a test pass</td>
-</tr>
- <tr>
-<td><span class="new_code">fail()</span></td><td>Sends a test failure</td>
-</tr>
- <tr>
-<td><span class="new_code">error()</span></td><td>Sends an exception event</td>
-</tr>
- <tr>
-<td><span class="new_code">sendMessage()</span></td><td>Sends a status message to those displays that support it</td>
-</tr>
- <tr>
-<td><span class="new_code">signal($type, $payload)</span></td><td>Sends a user defined message to the test reporter</td>
-</tr>
- <tr>
-<td><span class="new_code">dump($var)</span></td><td>Does a formatted <span class="new_code">print_r()</span> for quick and dirty debugging</td>
-</tr>
- <tr>
-<td><span class="new_code">swallowErrors()</span></td><td>Clears the error queue</td>
-</tr>
- </tbody>
-</table>
- </p>
-
- <p>
-<a class="target" name="extending_unit">
-<h2>Extending test cases</h2>
-</a>
-</p>
- <p>
- Of course additional test methods can be added to create
- specific types of test case too so as to extend framework...
-<pre>
-require_once('simpletest/unit_tester.php');
-<strong>
-class FileTester extends UnitTestCase {
- function FileTester($name = false) {
- $this-&gt;UnitTestCase($name);
- }
-
- function assertFileExists($filename, $message = '%s') {
- $this-&gt;assertTrue(
- file_exists($filename),
- sprintf($message, 'File [$filename] existence check'));
- }</strong>
-}
-</pre>
- Here the SimpleTest library is held in a folder called
- <em>simpletest</em> that is local.
- Substitute your own path for this.
- </p>
- <p>
- This new case can be now be inherited just like
- a normal test case...
-<pre>
-class FileTestCase extends <strong>FileTester</strong> {
-
- function setUp() {
- @unlink('../temp/test.txt');
- }
-
- function tearDown() {
- @unlink('../temp/test.txt');
- }
-
- function testCreation() {
- $writer = &amp;new FileWriter('../temp/test.txt');
- $writer-&gt;write('Hello');<strong>
- $this-&gt;assertFileExists('../temp/test.txt');</strong>
- }
-}
-</pre>
- </p>
- <p>
- If you want a test case that does not have all of the
- <span class="new_code">UnitTestCase</span> assertions,
- only your own and <span class="new_code">assertTrue()</span>,
- you need to extend the <span class="new_code">SimpleTestCase</span>
- class instead.
- It is found in <em>simple_test.php</em> rather than
- <em>unit_tester.php</em>.
- See <a href="group_test_documentation.html">later</a> if you
- want to incorporate other unit tester's
- test cases in your test suites.
- </p>
-
- <p>
-<a class="target" name="running_unit">
-<h2>Running a single test case</h2>
-</a>
-</p>
- <p>
- You won't often run single test cases except when bashing
- away at a module that is having difficulty and you don't
- want to upset the main test suite.
- Here is the scaffolding needed to run the a lone test case...
-<pre>
-&lt;?php
- require_once('simpletest/unit_tester.php');<strong>
- require_once('simpletest/reporter.php');</strong>
- require_once('../classes/writer.php');
-
- class FileTestCase extends UnitTestCase {
- function FileTestCase() {
- $this-&gt;UnitTestCase('File test');
- }
- }<strong>
-
- $test = &amp;new FileTestCase();
- $test-&gt;run(new HtmlReporter());</strong>
-?&gt;
-</pre>
- This script will run as is, but will output zero passes
- and zero failures until test methods are added.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>
diff --git a/tests/UnitTests/simpletest/docs/en/web_tester_documentation.html b/tests/UnitTests/simpletest/docs/en/web_tester_documentation.html
deleted file mode 100644
index 0ad5303c..00000000
--- a/tests/UnitTests/simpletest/docs/en/web_tester_documentation.html
+++ /dev/null
@@ -1,508 +0,0 @@
-<html>
-<head>
-<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Simple Test for PHP web script testing documentation</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>
-<span class="chosen">Web tester</span>
-</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>Web tester documentation</h1>
-<div class="content">
- <p>
-<a class="target" name="fetch">
-<h2>Fetching a page</h2>
-</a>
-</p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- <p>
- SimpleTest includes a special form of test case for the testing
- of web page actions.
- The <span class="new_code">WebTestCase</span> includes facilities
- for navigation, content and cookie checks and form handling.
- Usage of these test cases is similar to the
- <a href="unit_tester_documentation.html">UnitTestCase</a>...
-<pre>
-<strong>class TestOfLastcraft extends WebTestCase {
-}</strong>
-</pre>
- Here we are about to test the
- <a href="http://www/lastcraft.com/">Last Craft</a> site itself.
- If this test case is in a file called <em>lastcraft_test.php</em>
- then it can be loaded in a runner script just like unit tests...
-<pre>
-&lt;?php<strong>
- require_once('simpletest/web_tester.php');</strong>
- require_once('simpletest/reporter.php');
-
- $test = &amp;new GroupTest('Web site tests');<strong>
- $test-&gt;addTestFile('lastcraft_test.php');</strong>
- exit ($test-&gt;run(new TextReporter()) ? 0 : 1);
-?&gt;
-</pre>
- I am using the text reporter here to more clearly
- distinguish the web content from the test output.
- </p>
- <p>
- Nothing is being tested yet.
- We can fetch the home page by using the
- <span class="new_code">get()</span> method...
-<pre>
-class TestOfLastcraft extends WebTestCase {
- <strong>
- function testHomepage() {
- $this-&gt;assertTrue($this-&gt;get('http://www.lastcraft.com/'));
- }</strong>
-}
-</pre>
- The <span class="new_code">get()</span> 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 <span class="new_code">get()</span> method will still return true.
- </p>
- <p>
- Assuming that the web server for the Last Craft site is up
- (sadly not always the case), we should see...
-<pre class="shell">
-Web site tests
-OK
-Test cases run: 1/1, Failures: 0, Exceptions: 0
-</pre>
- All we have really checked is that any kind of page was
- returned.
- We don't yet know if it was the right one.
- </p>
-
- <p>
-<a class="target" name="content">
-<h2>Testing page content</h2>
-</a>
-</p>
- <p>
- To confirm that the page we think we are on is actually the
- page we are on, we need to verify the page content.
-<pre>
-class TestOfLastcraft extends WebTestCase {
-
- function testHomepage() {<strong>
- $this-&gt;get('http://www.lastcraft.com/');
- $this-&gt;assertWantedPattern('/why the last craft/i');</strong>
- }
-}
-</pre>
- 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.
- </p>
- <p>
- Here is the list of possible content assertions...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">assertTitle($title)</span></td><td>Pass if title is an exact match</td>
-</tr>
- <tr>
-<td><span class="new_code">assertWantedPattern($pattern)</span></td><td>A Perl pattern match against the page content</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoUnwantedPattern($pattern)</span></td><td>A Perl pattern match to not find content</td>
-</tr>
- <tr>
-<td><span class="new_code">assertWantedText($text)</span></td><td>Pass if matches visible and "alt" text</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoUnwantedText($text)</span></td><td>Pass if doesn't match visible and "alt" text</td>
-</tr>
- <tr>
-<td><span class="new_code">assertLink($label)</span></td><td>Pass if a link with this text is present</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoLink($label)</span></td><td>Pass if no link with this text is present</td>
-</tr>
- <tr>
-<td><span class="new_code">assertLinkById($id)</span></td><td>Pass if a link with this id attribute is present</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoLinkById($id)</span></td><td>Pass if no link with this id attribute is present</td>
-</tr>
- <tr>
-<td><span class="new_code">assertField($name, $value)</span></td><td>Pass if an input tag with this name has this value</td>
-</tr>
- <tr>
-<td><span class="new_code">assertFieldById($id, $value)</span></td><td>Pass if an input tag with this id has this value</td>
-</tr>
- <tr>
-<td><span class="new_code">assertResponse($codes)</span></td><td>Pass if HTTP response matches this list</td>
-</tr>
- <tr>
-<td><span class="new_code">assertMime($types)</span></td><td>Pass if MIME type is in this list</td>
-</tr>
- <tr>
-<td><span class="new_code">assertAuthentication($protocol)</span></td><td>Pass if the current challenge is this protocol</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoAuthentication()</span></td><td>Pass if there is no current challenge</td>
-</tr>
- <tr>
-<td><span class="new_code">assertRealm($name)</span></td><td>Pass if the current challenge realm matches</td>
-</tr>
- <tr>
-<td><span class="new_code">assertHeader($header, $content)</span></td><td>Pass if a header was fetched matching this value</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoUnwantedHeader($header)</span></td><td>Pass if a header was not fetched</td>
-</tr>
- <tr>
-<td><span class="new_code">assertHeaderPattern($header, $pattern)</span></td><td>Pass if a header was fetched matching this Perl regex</td>
-</tr>
- <tr>
-<td><span class="new_code">assertCookie($name, $value)</span></td><td>Pass if there is currently a matching cookie</td>
-</tr>
- <tr>
-<td><span class="new_code">assertNoCookie($name)</span></td><td>Pass if there is currently no cookie of this name</td>
-</tr>
- </tbody>
-</table>
- 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.
- </p>
- <p>
- So now we could instead test against the title tag with...
-<pre>
-<strong>$this-&gt;assertTitle('The Last Craft? Web developer tutorials on PHP, Extreme programming and Object Oriented development');</strong>
-</pre>
- As well as the simple HTML content checks we can check
- that the MIME type is in a list of allowed types with...
-<pre>
-<strong>$this-&gt;assertMime(array('text/plain', 'text/html'));</strong>
-</pre>
- 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...
-<pre>
-class TestOfLastcraft extends WebTestCase {
-
- function testRedirects() {
- $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
- $this-&gt;assertResponse(200);&lt;/strong&gt;
- }
-}
-</pre>
- 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 <span class="new_code">WebTestCase</span> 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...
-<pre>
-class TestOfLastcraft extends WebTestCase {
-
- function testHomepage() {<strong>
- $this-&gt;setMaximumRedirects(0);</strong>
- $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
- $this-&gt;assertResponse(200);
- }
-}
-</pre>
- The assertion now fails as expected...
-<pre class="shell">
-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
-</pre>
- We can modify the test to correctly assert redirects with...
-<pre>
-class TestOfLastcraft extends WebTestCase {
-
- function testHomepage() {
- $this-&gt;setMaximumRedirects(0);
- $this-&gt;get('http://www.lastcraft.com/test/redirect.php');
- $this-&gt;assertResponse(<strong>array(301, 302, 303, 307)</strong>);
- }
-}
-</pre>
- This now passes.
- </p>
-
- <p>
-<a class="target" name="navigation">
-<h2>Navigating a web site</h2>
-</a>
-</p>
- <p>
- 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...
-<pre>
-class TestOfLastcraft extends WebTestCase {
- ...
- function testContact() {
- $this-&gt;get('http://www.lastcraft.com/');<strong>
- $this-&gt;clickLink('About');
- $this-&gt;assertTitle('About Last Craft');</strong>
- }
-}
-</pre>
- The parameter is the text of the link.
- </p>
- <p>
- If the target is a button rather than an anchor tag, then
- <span class="new_code">clickSubmit()</span> should be used
- with the button title...
-<pre>
-<strong>$this-&gt;clickSubmit('Go!');</strong>
-</pre>
- </p>
- <p>
- The list of navigation methods is...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">getUrl()</span></td><td>The current location</td>
-</tr>
- <tr>
-<td><span class="new_code">get($url, $parameters)</span></td><td>Send a GET request with these parameters</td>
-</tr>
- <tr>
-<td><span class="new_code">post($url, $parameters)</span></td><td>Send a POST request with these parameters</td>
-</tr>
- <tr>
-<td><span class="new_code">head($url, $parameters)</span></td><td>Send a HEAD request without replacing the page content</td>
-</tr>
- <tr>
-<td><span class="new_code">retry()</span></td><td>Reload the last request</td>
-</tr>
- <tr>
-<td><span class="new_code">back()</span></td><td>Like the browser back button</td>
-</tr>
- <tr>
-<td><span class="new_code">forward()</span></td><td>Like the browser forward button</td>
-</tr>
- <tr>
-<td><span class="new_code">authenticate($name, $password)</span></td><td>Retry after a challenge</td>
-</tr>
- <tr>
-<td><span class="new_code">restart()</span></td><td>Restarts the browser as if a new session</td>
-</tr>
- <tr>
-<td><span class="new_code">getCookie($name)</span></td><td>Gets the cookie value for the current context</td>
-</tr>
- <tr>
-<td><span class="new_code">ageCookies($interval)</span></td><td>Ages current cookies prior to a restart</td>
-</tr>
- <tr>
-<td><span class="new_code">clearFrameFocus()</span></td><td>Go back to treating all frames as one page</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmit($label)</span></td><td>Click the first button with this label</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmitByName($name)</span></td><td>Click the button with this name attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">clickSubmitById($id)</span></td><td>Click the button with this ID attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImage($label, $x, $y)</span></td><td>Click an input tag of type image by title or alt text</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImageByName($name, $x, $y)</span></td><td>Click an input tag of type image by name</td>
-</tr>
- <tr>
-<td><span class="new_code">clickImageById($id, $x, $y)</span></td><td>Click an input tag of type image by ID attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">submitFormById($id)</span></td><td>Submit a form without the submit value</td>
-</tr>
- <tr>
-<td><span class="new_code">clickLink($label, $index)</span></td><td>Click an anchor by the visible label text</td>
-</tr>
- <tr>
-<td><span class="new_code">clickLinkById($id)</span></td><td>Click an anchor by the ID attribute</td>
-</tr>
- <tr>
-<td><span class="new_code">getFrameFocus()</span></td><td>The name of the currently selected frame</td>
-</tr>
- <tr>
-<td><span class="new_code">setFrameFocusByIndex($choice)</span></td><td>Focus on a frame counting from 1</td>
-</tr>
- <tr>
-<td><span class="new_code">setFrameFocus($name)</span></td><td>Focus on a frame by name</td>
-</tr>
- </tbody>
-</table>
- </p>
- <p>
- The parameters in the <span class="new_code">get()</span>, <span class="new_code">post()</span> or
- <span class="new_code">head()</span> 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.
- </p>
- <p>
- The <span class="new_code">retry()</span>, <span class="new_code">back()</span> and
- <span class="new_code">forward()</span> 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.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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
- <a href="form_testing_documentation.html">tools for testing web forms</a>
- as well.
- </p>
-
- <p>
-<a class="target" name="request">
-<h2>Modifying the request</h2>
-</a>
-</p>
- <p>
- 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...
- <table>
-<tbody>
- <tr>
-<td><span class="new_code">getTransportError()</span></td><td>The last socket error</td>
-</tr>
- <tr>
-<td><span class="new_code">showRequest()</span></td><td>Dump the outgoing request</td>
-</tr>
- <tr>
-<td><span class="new_code">showHeaders()</span></td><td>Dump the incoming headers</td>
-</tr>
- <tr>
-<td><span class="new_code">showSource()</span></td><td>Dump the raw HTML page content</td>
-</tr>
- <tr>
-<td><span class="new_code">ignoreFrames()</span></td><td>Do not load framesets</td>
-</tr>
- <tr>
-<td><span class="new_code">setCookie($name, $value)</span></td><td>Set a cookie from now on</td>
-</tr>
- <tr>
-<td><span class="new_code">addHeader($header)</span></td><td>Always add this header to the request</td>
-</tr>
- <tr>
-<td><span class="new_code">setMaximumRedirects($max)</span></td><td>Stop after this many redirects</td>
-</tr>
- <tr>
-<td><span class="new_code">setConnectionTimeout($timeout)</span></td><td>Kill the connection after this time between bytes</td>
-</tr>
- <tr>
-<td><span class="new_code">useProxy($proxy, $name, $password)</span></td><td>Make requests via this proxy URL</td>
-</tr>
- </tbody>
-</table>
- These methods are principally for debugging.
- </p>
-
- </div>
-<div class="copyright">
- Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
- </div>
-</body>
-</html>