diff options
author | xue <> | 2006-07-16 01:50:23 +0000 |
---|---|---|
committer | xue <> | 2006-07-16 01:50:23 +0000 |
commit | af68030fcf0c266300feb2c100149ecadef7d364 (patch) | |
tree | 76b7c8ad5d8227870b9ef10c3e7b92a36336b320 /tests/test_tools/simpletest/docs/en | |
parent | 4b78404c20490a615459267426ce9e6737bf4485 (diff) |
Merge from 3.0 branch till 1264.
Diffstat (limited to 'tests/test_tools/simpletest/docs/en')
12 files changed, 331 insertions, 332 deletions
diff --git a/tests/test_tools/simpletest/docs/en/authentication_documentation.html b/tests/test_tools/simpletest/docs/en/authentication_documentation.html index 0623023c..c90d61e5 100755 --- a/tests/test_tools/simpletest/docs/en/authentication_documentation.html +++ b/tests/test_tools/simpletest/docs/en/authentication_documentation.html @@ -21,9 +21,6 @@ <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> @@ -109,6 +106,19 @@ class AuthenticationTest extends WebTestCase { on the amount of detail you want to see. </p> <p> + One theme that runs through SimpleTest is the ability to use + <span class="new_code">SimpleExpectation</span> objects wherever a simple + match is not enough. + If you want only an approximate match to the realm for + example, you can do this... +<pre> +class AuthenticationTest extends WebTestCase { + function test401Header() { + $this->get('http://www.lastcraft.com/protected/'); + $this->assertRealm(<strong>new PatternExpectation('/simpletest/i')</strong>); + } +} +</pre> Most of the time we are not interested in testing the authentication itself, but want to get past it to test the pages underneath. @@ -116,7 +126,7 @@ class AuthenticationTest extends WebTestCase { an authentication response... <pre> class AuthenticationTest extends WebTestCase { - function testAuthentication() { + function testCanAuthenticate() { $this->get('http://www.lastcraft.com/protected/');<strong> $this->authenticate('Me', 'Secret');</strong> $this->assertTitle(...); @@ -208,9 +218,15 @@ class LogInTest extends WebTestCase { </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> + really worth testing this with... +<pre> +class LogInTest extends WebTestCase { + function testSessionCookieIsCorrectPattern() { + $this->get('http://www.my-site.com/login.php'); + $this->assertCookie('SID', <strong>new PatternExpectation('/[a-f0-9]{32}/i')</strong>); + } +} +</pre> 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. @@ -224,8 +240,8 @@ class LogInTest extends WebTestCase { $session = $this->getCookie('SID'); $this->setField('u', 'Me'); $this->setField('p', 'Secret'); - $this->clickSubmit('Log in'); - $this->assertWantedPattern('/Welcome Me/'); + $this->click('Log in'); + $this->assertText('Welcome Me'); $this->assertCookie('SID', $session);</strong> } } @@ -243,7 +259,7 @@ class LogInTest extends WebTestCase { $this->get('http://www.my-site.com/login.php');<strong> $this->setCookie('SID', 'Some other session'); $this->get('http://www.my-site.com/restricted.php');</strong> - $this->assertWantedPattern('/Access denied/'); + $this->assertText('Access denied'); } } </pre> @@ -266,12 +282,12 @@ class LogInTest extends WebTestCase { $this->get('http://www.my-site.com/login.php'); $this->setField('u', 'Me'); $this->setField('p', 'Secret'); - $this->clickSubmit('Log in'); - $this->assertWantedPattern('/Welcome Me/');<strong> + $this->click('Log in'); + $this->assertText('Welcome Me');<strong> $this->restart(); $this->get('http://www.my-site.com/restricted.php'); - $this->assertWantedPattern('/Access denied/');</strong> + $this->assertText('Access denied');</strong> } } </pre> @@ -297,13 +313,13 @@ class LogInTest extends WebTestCase { $this->get('http://www.my-site.com/login.php'); $this->setField('u', 'Me'); $this->setField('p', 'Secret'); - $this->clickSubmit('Log in'); - $this->assertWantedPattern('/Welcome Me/'); + $this->click('Log in'); + $this->assertText('Welcome Me'); <strong> $this->ageCookies(3600);</strong> $this->restart(); $this->get('http://www.my-site.com/restricted.php'); - $this->assertWantedPattern('/Access denied/'); + $this->assertText('Access denied'); } } </pre> diff --git a/tests/test_tools/simpletest/docs/en/browser_documentation.html b/tests/test_tools/simpletest/docs/en/browser_documentation.html index ef54aaea..f6046a9d 100755 --- a/tests/test_tools/simpletest/docs/en/browser_documentation.html +++ b/tests/test_tools/simpletest/docs/en/browser_documentation.html @@ -21,9 +21,6 @@ <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> @@ -76,9 +73,9 @@ $browser = &new SimpleBrowser(); $browser->get('http://php.net/'); - $browser->clickLink('reporting bugs'); - $browser->clickLink('statistics'); - $page = $browser->clickLink('PHP 5 bugs only'); + $browser->click('reporting bugs'); + $browser->click('statistics'); + $page = $browser->click('PHP 5 bugs only'); preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches); print $matches[1]; ?></strong> @@ -298,13 +295,21 @@ <tr> <td><span class="new_code">useFrames()</span></td><td>Enables frames support</td> </tr> + <tr> +<td><span class="new_code">ignoreCookies()</span></td><td>Disables sending and receiving of cookies</td> +</tr> + <tr> +<td><span class="new_code">useCookies()</span></td><td>Enables cookie 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 + <span class="new_code">SimpleBrowser::ignoreFrames()</span>, + <span class="new_code">SimpleBrowser::useFrames()</span>, + <span class="new_code">SimpleBrowser::ignoreCookies()</span> and + <span class="new_code">SimpleBrowser::useCokies()</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 @@ -332,7 +337,7 @@ class TestOfRegistration extends UnitTestCase { $browser->get('http://my-site.com/register.php'); $browser->setField('email', 'me@here'); $browser->setField('password', 'Secret'); - $browser->clickSubmit('Register'); + $browser->click('Register'); <strong> $authenticator = &new Authenticator(); $member = &$authenticator->findByEmail('me@here'); @@ -361,14 +366,14 @@ class TestOfSecurity extends UnitTestCase { $first->get('http://my-site.com/login.php'); $first->setField('name', 'Me'); $first->setField('password', 'Secret'); - $first->clickSubmit('Enter'); + $first->click('Enter'); $this->assertEqual($first->getTitle(), 'Welcome'); $second = &new SimpleBrowser(); $second->get('http://my-site.com/login.php'); $second->setField('name', 'Me'); $second->setField('password', 'Secret'); - $second->clickSubmit('Enter'); + $second->click('Enter'); $this->assertEqual($second->getTitle(), 'Access Denied');</strong> } } diff --git a/tests/test_tools/simpletest/docs/en/expectation_documentation.html b/tests/test_tools/simpletest/docs/en/expectation_documentation.html index 0165988c..bd189b94 100755 --- a/tests/test_tools/simpletest/docs/en/expectation_documentation.html +++ b/tests/test_tools/simpletest/docs/en/expectation_documentation.html @@ -23,9 +23,6 @@ <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> @@ -101,8 +98,8 @@ <pre> class TestOfNewsService extends UnitTestCase { ... - function testConnectionFailure() {<strong> - $writer = &new MockWriter($this); + function testConnectionFailure() {<strong> + $writer = &new MockWriter(); $writer->expectOnce('write', array( 'Cannot connect to news service ' . '"BBC News" at this time. ' . @@ -110,8 +107,6 @@ class TestOfNewsService extends UnitTestCase { $service = &new NewsService('BBC News'); $service->publish($writer); - - $writer->tally();</strong> } } </pre> @@ -129,15 +124,13 @@ class TestOfNewsService extends UnitTestCase { class TestOfNewsService extends UnitTestCase { ... function testConnectionFailure() { - $writer = &new MockWriter($this);<strong> + $writer = &new MockWriter();<strong> $writer->expectOnce( 'write', - array(new WantedPatternExpectation('/cannot connect/i')));</strong> + array(new PatternExpectation('/cannot connect/i')));</strong> $service = &new NewsService('BBC News'); $service->publish($writer); - - $writer->tally(); } } </pre> @@ -179,10 +172,10 @@ class TestOfNewsService extends UnitTestCase { <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> +<td><span class="new_code">PatternExpectation</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> +<td><span class="new_code">NoPatternExpectation</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> @@ -208,29 +201,26 @@ class TestOfNewsService extends UnitTestCase { </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>. + from mock objects, but also for selecting behaviour for the + <a href="mock_objects_documentation.html">mock objects</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 + Suppose we want an authorisation server mock to simulate a successful login only if it receives a valid session object. We can do this as follows... <pre> -Stub::generate('Authorisation'); +Mock::generate('Authorisation'); <strong> -$authorisation = new StubAuthorisation(); +$authorisation = new MockAuthorisation(); $authorisation->setReturnValue( 'isAllowed', true, array(new IsAExpectation('Session', 'Must be a session'))); $authorisation->setReturnValue('isAllowed', false);</strong> </pre> - We have set the default stub behaviour to return false when + We have set the default mock 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. @@ -299,14 +289,14 @@ $authorisation->setReturnValue('isAllowed', false);</strong> </p> <p> The most crude way of doing this is to use the - <span class="new_code">SimpleTest::assertExpectation()</span> method to + <span class="new_code">SimpleTest::assert()</span> method to test against it directly... <pre> <strong>class TestOfNetworking extends UnitTestCase { ... function testGetValidIp() { $server = &new Server(); - $this->assertExpectation( + $this->assert( new ValidIp(), $server->getIp(), 'Server IP address->%s'); @@ -327,7 +317,7 @@ $authorisation->setReturnValue('isAllowed', false);</strong> class TestOfNetworking extends UnitTestCase { ...<strong> function assertValidIp($ip, $message = '%s') { - $this->assertExpectation(new ValidIp(), $ip, $message); + $this->assert(new ValidIp(), $ip, $message); }</strong> function testGetValidIp() { diff --git a/tests/test_tools/simpletest/docs/en/form_testing_documentation.html b/tests/test_tools/simpletest/docs/en/form_testing_documentation.html index b1e15b3d..50b634c0 100755 --- a/tests/test_tools/simpletest/docs/en/form_testing_documentation.html +++ b/tests/test_tools/simpletest/docs/en/form_testing_documentation.html @@ -21,9 +21,6 @@ <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> @@ -96,7 +93,9 @@ class SimpleFormTests extends WebTestCase { 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" + "A default". + As usual, we could use a pattern expectation instead if a fixed + string. </p> <p> We could submit the form straight away, but first we'll change @@ -108,7 +107,7 @@ class SimpleFormTests extends WebTestCase { $this->get('http://www.my-site.com/'); $this->assertField('a', 'A default');<strong> $this->setField('a', 'New value'); - $this->clickSubmit('Go');</strong> + $this->click('Go');</strong> } } </pre> @@ -235,7 +234,7 @@ class SimpleFormTests extends WebTestCase { $this->get('http://www.lastcraft.com/form_testing_documentation.php'); $this->assertField('crud', array('c', 'r', 'u', 'd')); $this->setField('crud', array('r')); - $this->clickSubmit('Enable Privileges'); + $this->click('Enable Privileges'); }</strong> } </pre> @@ -261,7 +260,7 @@ class SimpleFormTests extends WebTestCase { $this->post( 'http://www.my-site.com/add_user.php', array('type' => 'superuser')); - $this->assertNoUnwantedPattern('/user created/i'); + $this->assertNoText('user created'); }</strong> } </pre> diff --git a/tests/test_tools/simpletest/docs/en/group_test_documentation.html b/tests/test_tools/simpletest/docs/en/group_test_documentation.html index adbc66ef..1e14d31e 100755 --- a/tests/test_tools/simpletest/docs/en/group_test_documentation.html +++ b/tests/test_tools/simpletest/docs/en/group_test_documentation.html @@ -21,9 +21,6 @@ <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> @@ -87,7 +84,7 @@ class MyFileTestCase extends UnitTestCase { ... } - SimpleTestOptions::ignore('MyFileTestCase');</strong> + SimpleTest::ignore('MyFileTestCase');</strong> class FileTester extends MyFileTestCase { ... diff --git a/tests/test_tools/simpletest/docs/en/index.html b/tests/test_tools/simpletest/docs/en/index.html index 04797272..c7183c49 100755 --- a/tests/test_tools/simpletest/docs/en/index.html +++ b/tests/test_tools/simpletest/docs/en/index.html @@ -24,9 +24,6 @@ <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> @@ -101,26 +98,22 @@ We start by creating a test script which we will call <em>tests/log_test.php</em> and populate it as follows... <pre> -<strong><?php -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); -require_once('../classes/log.php'); -?></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> -<?php +<?php<strong> require_once('simpletest/unit_tester.php'); require_once('simpletest/reporter.php'); require_once('../classes/log.php'); -<strong> + class TestOfLogging extends UnitTestCase { }</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. + The <span class="new_code">TestOfLogging</span> is our frst test case and it's + currently empty. + </p> + <p> 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 @@ -376,21 +369,15 @@ Mock::generate('Log');</strong> class TestOfSessionLogging extends UnitTestCase { function testLogInIsLogged() {<strong> - $log = &new MockLog($this); + $log = &new MockLog(); $log->expectOnce('message', array('User fred logged in.'));</strong> $session_pool = &new SessionPool($log); - $session_pool->logIn('fred');<strong> - $log->tally();</strong> + $session_pool->logIn('fred'); } } ?> </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 + The 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 @@ -399,6 +386,13 @@ class TestOfSessionLogging extends UnitTestCase { becoming too specific. </p> <p> + If the mock reaches the end of the test case without the + method being called, the <span class="new_code">expectOnce()</span> + expectation will trigger a test failure. + In other words the mocks can detect the absence of + behaviour as well as the presence. + </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 @@ -439,12 +433,12 @@ class TestOfAbout extends WebTestCase { function setUp() { $this->get('http://test-server/index.php'); - $this->clickLink('About'); + $this->click('About'); } function testSearchEngineOptimisations() { $this->assertTitle('A long title about us for search engines'); - $this->assertWantedPattern('/a popular keyphrase/i'); + $this->assertPattern('/a popular keyphrase/i'); } }</strong> $test = &new TestOfAbout(); diff --git a/tests/test_tools/simpletest/docs/en/mock_objects_documentation.html b/tests/test_tools/simpletest/docs/en/mock_objects_documentation.html index 2f8a1f90..eb32c619 100755 --- a/tests/test_tools/simpletest/docs/en/mock_objects_documentation.html +++ b/tests/test_tools/simpletest/docs/en/mock_objects_documentation.html @@ -21,9 +21,6 @@ <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> @@ -76,7 +73,17 @@ </p> <p> If mock objects only behaved as actors they would simply be - known as <a href="server_stubs_documentation.html">server stubs</a>. + known as server stubs. + This was originally a pattern named by Robert Binder (Testing + object-oriented systems: models, patterns, and tools, + Addison-Wesley) in 1999. + </p> + <p> + 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> However, the mock objects not only play a part (by supplying chosen @@ -87,6 +94,8 @@ If expectations are not met they save us the effort of writing a failed test assertion by performing that duty on our behalf. + </p> + <p> 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. @@ -138,7 +147,7 @@ Mock::generate('DatabaseConnection'); class MyTestCase extends UnitTestCase { function testSomething() { - $connection = &new MockDatabaseConnection($this); + $connection = &new MockDatabaseConnection(); } }</strong> </pre> @@ -155,19 +164,27 @@ class MyTestCase extends UnitTestCase { </a> </p> <p> - The mock version of a class has all the methods of the original + The mock version of a class has all the methods of the original, so that operations like <span class="new_code">$connection->query()</span> are still legal. - As with stubs we can replace the default null return values... + The return value will be <span class="new_code">null</span>, + but we can change that with... <pre> -<strong>$connection->setReturnValue('query', 37);</strong> +<strong>$connection->setReturnValue('query', 37)</strong> </pre> Now every time we call <span class="new_code">$connection->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 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> We can also add extra methods to the mock when generating it and choose our own class name... <pre> @@ -180,8 +197,12 @@ class MyTestCase extends UnitTestCase { 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... + 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() { @@ -191,7 +212,8 @@ class Iterator { } } </pre> - Again, assuming that this iterator only returns text until it + 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> @@ -200,7 +222,7 @@ Mock::generate('Iterator'); class IteratorTest extends UnitTestCase() { function testASequence() {<strong> - $iterator = &new MockIterator($this); + $iterator = &new MockIterator(); $iterator->setReturnValue('next', false); $iterator->setReturnValueAt(0, 'next', 'First string'); $iterator->setReturnValueAt(1, 'next', 'Second string');</strong> @@ -218,7 +240,10 @@ class IteratorTest extends UnitTestCase() { The constant one is a kind of default if you like. </p> <p> - A repeat of the stubbed information holder with name/value pairs... + 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() { @@ -237,7 +262,7 @@ class Configuration { we want different results for different keys. Luckily the mocks have a filter system... <pre> -<strong>$config = &new MockConfiguration($this); +<strong>$config = &new MockConfiguration(); $config->setReturnValue('getValue', 'primary', array('db_host')); $config->setReturnValue('getValue', 'admin', array('db_user')); $config->setReturnValue('getValue', 'secret', array('db_password'));</strong> @@ -258,9 +283,35 @@ $config->getValue('db_user') a complete match is found. </p> <p> + You can set a default argument argument like so... +<pre> +<strong> +$config->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->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 mock rather than a copy. - Again this is identical to the server stubs mechanism... + The PHP4 copy semantics force us to use a different method + for this. + You might be simulating a container for example... <pre> class Thing { } @@ -276,14 +327,79 @@ class Vector { In this case you can set a reference into the mock's return list... <pre> -$thing = new Thing();<strong> -$vector = &new MockVector($this); +$thing = &new Thing();<strong> +$vector = &new MockVector(); $vector->setReturnReference('get', $thing, array(12));</strong> </pre> With this arrangement you know that every time <span class="new_code">$vector->get(12)</span> is called it will return the same <span class="new_code">$thing</span> each time. + This is compatible with PHP5 as well. + </p> + <p> + These three factors, timing, parameters and whether to copy, + can be combined orthogonally. + For example... +<pre> +$complex = &new MockComplexThing(); +$stuff = &new Stuff();<strong> +$complex->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 mocked using the mechanics above. + </p> + <p> + Here's how... +<pre> +Mock::generate('DatabaseConnection'); +Mock::generate('ResultIterator'); + +class DatabaseTest extends UnitTestCase { + + function testUserFinder() {<strong> + $result = &new MockResultIterator(); + $result->setReturnValue('next', false); + $result->setReturnValueAt(0, 'next', array(1, 'tom')); + $result->setReturnValueAt(1, 'next', array(3, 'dick')); + $result->setReturnValueAt(2, 'next', array(6, 'harry')); + + $connection = &new MockDatabaseConnection(); + $connection->setReturnValue('query', false); + $connection->setReturnReference( + 'query', + $result, + array('select id, name from users'));</strong> + + $finder = &new UserFinder($connection); + $this->assertIdentical( + $finder->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> @@ -388,18 +504,16 @@ Mock::generate('Log'); class LoggingSessionPoolTest extends UnitTestCase { ... function testFindSessionLogging() {<strong> - $session = &new MockSession($this); - $pool = &new MockSessionPool($this); + $session = &new MockSession(); + $pool = &new MockSessionPool(); $pool->setReturnReference('findSession', $session); $pool->expectOnce('findSession', array('abc')); - $log = &new MockLog($this); + $log = &new MockLog(); $log->expectOnce('message', array('Starting session abc')); $logging_pool = &new LoggingSessionPool($pool, $log); - $this->assertReference($logging_pool->findSession('abc'), $session); - $pool->tally(); - $log->tally();</strong> + $this->assertReference($logging_pool->findSession('abc'), $session);</strong> } } </pre> @@ -427,15 +541,6 @@ class LoggingSessionPoolTest extends UnitTestCase { 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 @@ -448,11 +553,6 @@ class LoggingSessionPoolTest extends UnitTestCase { <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 @@ -477,11 +577,11 @@ class LoggingSessionPoolTest extends UnitTestCase { </thead> <tbody> <tr> - <td><span class="new_code">expectArguments($method, $args)</span></td> + <td><span class="new_code">expect($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><span class="new_code">expectAt($timing, $method, $args)</span></td> <td style="text-align: center">No</td> </tr> <tr> @@ -589,8 +689,8 @@ class LoggingSessionPoolTest extends UnitTestCase { <strong> Mock::generate('Connection', 'BasicMockConnection'); class MockConnection extends BasicMockConnection { - function MockConnection(&$test, $wildcard = '*') { - $this->BasicMockConnection($test, $wildcard); + function MockConnection() { + $this->BasicMockConnection(); $this->setReturn('query', false); } }</strong> @@ -619,92 +719,6 @@ class LoggingSessionPoolTest extends UnitTestCase { 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>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><?php - require_once('simpletest/mock_objects.php'); - - class MyMock extends SimpleMock() { - function MyMock(&$test, $wildcard) { - $this->SimpleMock($test, $wildcard); - } - - function _assertTrue($assertion, $message) { - $test = &$this->getTest(); - $test->assertion($message, $assertion); - } - } -?></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> -<?php - require_once('simpletst/mock_objects.php'); - - class MyMock extends SimpleMock() { - function MyMock($test, $wildcard) { - $this->SimpleMock(&$test, $wildcard); - } - - function _assertTrue($assertion, $message , &$test) { - $test->assertion($message, $assertion); - } - }<strong> - SimpleTestOptions::setMockBaseClass('MyMock');</strong> -?> -</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 diff --git a/tests/test_tools/simpletest/docs/en/overview.html b/tests/test_tools/simpletest/docs/en/overview.html index d4965de3..5d4e80e2 100755 --- a/tests/test_tools/simpletest/docs/en/overview.html +++ b/tests/test_tools/simpletest/docs/en/overview.html @@ -23,9 +23,6 @@ <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> @@ -151,8 +148,7 @@ class <strong>MySiteTest</strong> extends WebTestCase { 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". + then you should check-out the code from Sourceforge CVS directly. <table> <thead> <tr> @@ -163,12 +159,12 @@ class <strong>MySiteTest</strong> extends WebTestCase { <tr> <td>Unit test case</td> <td>Core test case class and assertions</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Html display</td> <td>Simplest possible display</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Autoloading of test cases</td> @@ -176,41 +172,20 @@ class <strong>MySiteTest</strong> extends WebTestCase { Reading a file with test cases and loading them into a group test automatically </td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> - <td>Mock objects code generator</td> + <td>Mock objects</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> + <td style="color: green;">1.0</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> + <td style="color: green;">1.0</td> </tr> <tr> <td>Partial mocks</td> @@ -218,32 +193,32 @@ class <strong>MySiteTest</strong> extends WebTestCase { Mocking parts of a class for testing less than a class or for complex simulations </td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Web cookie handling</td> <td>Correct handling of cookies when fetching pages</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Following redirects</td> <td>Page fetching automatically follows 300 redirects</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</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> + <td style="color: green;">1.0</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> + <td style="color: green;">1.0</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> + <td style="color: green;">1.0</td> </tr> <tr> <td>XML output and parsing</td> @@ -251,25 +226,15 @@ class <strong>MySiteTest</strong> extends WebTestCase { Allows multi host testing and the integration of acceptance testing extensions </td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</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>Browser component</td> <td> Exposure of lower level web browser interface for more detailed test cases </td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>HTTP authentication</td> @@ -277,31 +242,39 @@ class <strong>MySiteTest</strong> extends WebTestCase { 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> + <td style="color: green;">1.0</td> </tr> <tr> <td>SSL support</td> <td>Can connect to https: pages</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Proxy support</td> <td>Can connect via. common proxies</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> </tr> <tr> <td>Frames support</td> <td>Handling of frames in web test cases</td> - <td style="color: green;">Done</td> + <td style="color: green;">1.0</td> + </tr> + <tr> + <td>File upload testing</td> + <td>Can simulate the input type file tag</td> + <td style="color: green;">1.0.1</td> + </tr> + <tr> + <td>Mocking interfaces</td> + <td> + Can generate mock objects to interfaces as well as classes + and class interfaces are carried for type hints + </td> + <td style="color: green;">1.0.1</td> </tr> <tr> - <td>Improved display</td> - <td>Better web GUI with tree display of test cases</td> + <td>Reporting machinery enhancements</td> + <td>Improved message passing for better cooperation with IDEs</td> <td style="color: red;">1.1</td> </tr> <tr> @@ -310,28 +283,43 @@ class <strong>MySiteTest</strong> extends WebTestCase { <td style="color: red;">1.1</td> </tr> <tr> - <td>File upload testing</td> - <td>Can simulate the input type file tag</td> + <td>Testing exceptions</td> + <td>Similar to testing PHP errors</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>IFrame support</td> + <td>Reads IFrame content that can be refreshed</td> + <td style="color: red;">1.1</td> + </tr> + <tr> + <td>Improved mock interface</td> + <td>More compact way of expressing mocks</td> <td style="color: red;">2.0</td> </tr> <tr> - <td>Testing exceptions</td> - <td>Similar to testing PHP errors</td> + <td>HTML table assertions</td> + <td>Can match table elements to numerical assertions</td> + <td style="color: red;">2.0</td> + </tr> + <tr> + <td>XPath searching of HTML elements</td> + <td>More flexible content matching</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>Alternate HTML parsers</td> + <td>Can detect compiled parsers for performance improvements</td> <td style="color: red;">2.0</td> </tr> + <tr> + <td>Javascript suport</td> + <td>Use of PECL module to add Javascript</td> + <td style="color: red;">3.0</td> + </tr> </tbody> </table> - PHP5 migraton will start straight after the version 1.1 series, + PHP5 migraton will start straight after the version 1.0.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. @@ -375,18 +363,6 @@ class <strong>MySiteTest</strong> extends WebTestCase { 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> @@ -394,14 +370,15 @@ class <strong>MySiteTest</strong> extends WebTestCase { 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://www.mockobjects.com/MocksObjectsPaper.html">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 + There are plenty of web testing tools, but the scriptable ones + are mostly 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>, @@ -409,6 +386,13 @@ class <strong>MySiteTest</strong> extends WebTestCase { 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. + </p> + <p> + A new generation of tools that run directly in the web browser + are now available. + These include + <a href="http://www.openqa.org/selenium/">Selenium</a> and + <a href="http://wtr.rubyforge.org/">Watir</a>. As SimpleTest does not support JavaScript you would probably have to look at these tools anyway if you have highly dynamic pages. diff --git a/tests/test_tools/simpletest/docs/en/partial_mocks_documentation.html b/tests/test_tools/simpletest/docs/en/partial_mocks_documentation.html index 20749415..6d7b6243 100755 --- a/tests/test_tools/simpletest/docs/en/partial_mocks_documentation.html +++ b/tests/test_tools/simpletest/docs/en/partial_mocks_documentation.html @@ -21,9 +21,6 @@ <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> diff --git a/tests/test_tools/simpletest/docs/en/reporter_documentation.html b/tests/test_tools/simpletest/docs/en/reporter_documentation.html index 44be8b1e..ead61175 100755 --- a/tests/test_tools/simpletest/docs/en/reporter_documentation.html +++ b/tests/test_tools/simpletest/docs/en/reporter_documentation.html @@ -21,9 +21,6 @@ <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> diff --git a/tests/test_tools/simpletest/docs/en/unit_test_documentation.html b/tests/test_tools/simpletest/docs/en/unit_test_documentation.html index 6aa8d8a7..47b61eca 100755 --- a/tests/test_tools/simpletest/docs/en/unit_test_documentation.html +++ b/tests/test_tools/simpletest/docs/en/unit_test_documentation.html @@ -21,9 +21,6 @@ <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> @@ -164,6 +161,12 @@ class FileTestCase extends UnitTestCase { <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">assertWithinMargin($x, $y, $m)</span></td><td>Fail if abs($x - $y) < $m is false</td> +</tr> + <tr> +<td><span class="new_code">assertOutsideMargin($x, $y, $m)</span></td><td>Fail if abs($x - $y) < $m 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> @@ -176,19 +179,19 @@ class FileTestCase extends UnitTestCase { <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> +<td><span class="new_code">assertPattern($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> +<td><span class="new_code">assertNoPattern($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> +<td><span class="new_code">assertError($x)</span></td><td>Fail if no PHP error or incorrect message/expectation</td> </tr> <tr> -<td><span class="new_code">assertErrorPattern($p)</span></td><td>Fail unless the error matches the regex $p</td> +<td><span class="new_code">assertExpectation($e)</span></td><td>Fail on failed expectation object</td> </tr> </tbody> </table> @@ -226,7 +229,7 @@ $this->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->assertWantedPattern('/hello/i', 'Hello world');</strong> +<strong>$this->assertPattern('/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>. diff --git a/tests/test_tools/simpletest/docs/en/web_tester_documentation.html b/tests/test_tools/simpletest/docs/en/web_tester_documentation.html index 51f604be..99dacacc 100755 --- a/tests/test_tools/simpletest/docs/en/web_tester_documentation.html +++ b/tests/test_tools/simpletest/docs/en/web_tester_documentation.html @@ -21,9 +21,6 @@ <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> @@ -153,7 +150,7 @@ class TestOfLastcraft extends WebTestCase { function testHomepage() {<strong> $this->get('http://www.lastcraft.com/'); - $this->assertWantedPattern('/why the last craft/i');</strong> + $this->assertTest('Why the last craft');</strong> } } </pre> @@ -169,16 +166,16 @@ class TestOfLastcraft extends WebTestCase { <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> +<td><span class="new_code">assertPattern($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> +<td><span class="new_code">assertNoPattern($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> +<td><span class="new_code">assertText($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> +<td><span class="new_code">assertNoText($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> @@ -217,10 +214,7 @@ class TestOfLastcraft extends WebTestCase { <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> +<td><span class="new_code">assertNoHeader($header)</span></td><td>Pass if a header was not fetched</td> </tr> <tr> <td><span class="new_code">assertCookie($name, $value)</span></td><td>Pass if there is currently a matching cookie</td> @@ -241,6 +235,10 @@ class TestOfLastcraft extends WebTestCase { <pre> <strong>$this->assertTitle('The Last Craft? Web developer tutorials on PHP, Extreme programming and Object Oriented development');</strong> </pre> + ...or, if that is too long and fragile... +<pre> +<strong>$this->assertTitle(new PatternExpectation('/The Last Craft/'));</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> @@ -319,7 +317,7 @@ class TestOfLastcraft extends WebTestCase { function testContact() { $this->get('http://www.lastcraft.com/');<strong> $this->clickLink('About'); - $this->assertTitle('About Last Craft');</strong> + $this->assertTitle(new PatternExpectation('/About Last Craft/'));</strong> } } </pre> @@ -327,11 +325,16 @@ class TestOfLastcraft extends WebTestCase { </p> <p> If the target is a button rather than an anchor tag, then - <span class="new_code">clickSubmit()</span> should be used + <span class="new_code">clickSubmit()</span> can be used with the button title... <pre> <strong>$this->clickSubmit('Go!');</strong> </pre> + If you are not sure or don't care, the usual case, then just + use the <span class="new_code">click()</span> method... +<pre> +<strong>$this->click('Go!');</strong> +</pre> </p> <p> The list of navigation methods is... |