From e7e7c7403b1ffffdf1a7a4bb9e1de752fe1c72db Mon Sep 17 00:00:00 2001 From: wei <> Date: Wed, 5 Jul 2006 07:45:41 +0000 Subject: clean up tests --- .../docs/en/server_stubs_documentation.html | 388 --------------------- 1 file changed, 388 deletions(-) delete mode 100644 tests/UnitTests/simpletest/docs/en/server_stubs_documentation.html (limited to 'tests/UnitTests/simpletest/docs/en/server_stubs_documentation.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 @@ - - - -SimpleTest for PHP server stubs documentation - - - - -

Server stubs documentation

-
-

- -

What are server stubs?

- -

-

- 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. -

- -

- -

Creating server stubs

- -

-

- All we need is an existing class, say a database connection - that looks like this... -

-class DatabaseConnection {
-    function DatabaseConnection() {
-    }
-    
-    function query() {
-    }
-    
-    function selectQuery() {
-    }
-}
-
- 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... -
-require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-Stub::generate('DatabaseConnection');
-
- This generates a clone class called - StubDatabaseConnection. - We can now create instances of the new class within - our prototype script... -
-require_once('simpletest/mock_objects.php');
-require_once('database_connection.php');
-Stub::generate('DatabaseConnection');
-
-$connection = new StubDatabaseConnection();
-
-
- The stub version of a class has all the methods of the original - so that operations like - $connection->query() are still - legal. - The return value will be null, - but we can change that with... -
-$connection->setReturnValue('query', 37)
-
- Now every time we call - $connection->query() 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. -

- -

- -

Simulation patterns

- -

-

- 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... -

-class Iterator {
-    function Iterator() {
-    }
-    
-    function next() {
-    }
-}
-
- 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... -
-Stub::generate('Iterator');
-
-$iterator = new StubIterator();
-$iterator->setReturnValue('next', false);
-$iterator->setReturnValueAt(0, 'next', 'First string');
-$iterator->setReturnValueAt(1, 'next', 'Second string');
-
- When next() 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 false 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. -

-

- Another tricky situation is an overloaded - get() operation. - An example of this is an information holder with name/value pairs. - Say we have a configuration class like... -

-class Configuration {
-    function Configuration() {
-    }
-    
-    function getValue($key) {
-    }
-}
-
- 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 - getValue() method and yet - we want different results for different keys. - Luckily the stubs have a filter system... -
-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'));
-
- 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 - getValue() method invoked - like this... -
-$config->getValue('db_user');
-
- ...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. -

-

- You can set a default argument argument like so... -

-
-$config->setReturnValue('getValue', false, array('*'));
-
- This is not the same as setting the return value without - any argument requirements like this... -
-
-$config->setReturnValue('getValue', false);
-
- 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. -

-

- 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... -

-class Thing {
-}
-
-class Vector {
-    function Vector() {
-    }
-    
-    function get($index) {
-    }
-}
-
- In this case you can set a reference into the stub's - return list... -
-Stub::generate('Vector');
-
-$thing = new Thing();
-$vector = &new StubVector();
-$vector->setReturnReference('get', $thing, array(12));
-
- With this arrangement you know that every time - $vector->get(12) is - called it will return the same - $thing each time. -

-

- These three factors, timing, parameters and whether to copy, - can be combined orthogonally. - For example... -

-$complex = &new StubComplexThing();
-$stuff = new Stuff();
-$complex->setReturnReferenceAt(3, 'get', $stuff, array('*', 1));
-
- This will return the $stuff 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. -

-

- 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 next() giving - one row until false. - This sounds like a simulation nightmare, but in fact it can all - be stubbed using the mechanics above. -

-

- Here's how... -

-Stub::generate('DatabaseConnection');
-Stub::generate('ResultIterator');
-
-class DatabaseTest extends UnitTestCase {
-    
-    function testUserFinder() {
-        $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'));
-                
-        $finder = &new UserFinder($connection);
-        $this->assertIdentical(
-                $finder->findNames(),
-                array('tom', 'dick', 'harry'));
-    }
-}
-
- Now only if our - $connection is called with the correct - query() will the - $result be returned that is - itself exhausted after the third call to next(). - This should be enough - information for our UserFinder class, - the class actually - being tested here, to come up with goods. - A very precise test and not a real database in sight. -

- -

- -

Stub creation options

- -

-

- There are some additional options when creating stubs. - At the generation stage we can change the class name... -

-Stub::generate('Iterator', 'MyStubIterator');
-$iterator = &new MyStubIterator();
-
-
- 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... -
-class Iterator {
-}
-Stub::generate('Iterator', 'PrototypeIterator', array('next', 'isError'));
-$iterator = &new PrototypeIterator();
-$iterator->setReturnValue('next', 0);
-
-
- The next() and - isError() methods can now have - return values set just as if they existed in the original class. -

-

- One other esoteric way of customising the stubs is to change - the default wildcard used for parameter matching. -

-Stub::generate('Connection');
-$iterator = &new StubConnection('wild');
-$iterator->setReturnValue('query', array('id' => 33), array('wild'));
-
-
- 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". -

- -
- - - -- cgit v1.2.3