diff options
Diffstat (limited to 'test_tools/simpletest/docs/en/server_stubs_documentation.html')
-rwxr-xr-x | test_tools/simpletest/docs/en/server_stubs_documentation.html | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/test_tools/simpletest/docs/en/server_stubs_documentation.html b/test_tools/simpletest/docs/en/server_stubs_documentation.html deleted file mode 100755 index 4b18bb0b..00000000 --- a/test_tools/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->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->setReturnValue('query', 37)</strong> -</pre> - Now every time we call - <span class="new_code">$connection->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->setReturnValue('next', false); -$iterator->setReturnValueAt(0, 'next', 'First string'); -$iterator->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 = &new StubConfiguration(); -$config->setReturnValue('getValue', 'primary', array('db_host')); -$config->setReturnValue('getValue', 'admin', array('db_user')); -$config->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->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->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 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 = &new StubVector(); -$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. - </p> - <p> - These three factors, timing, parameters and whether to copy, - can be combined orthogonally. - For example... -<pre> -$complex = &new StubComplexThing(); -$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 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 = &new StubResultIterator(); - $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 StubDatabaseConnection(); - $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> -<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 = &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 = &new PrototypeIterator(); -$iterator->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 = &new StubConnection('wild'); -$iterator->setReturnValue('query', array('id' => 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> |