From 61bb16ee2e5f0a66234e1575242169a10fde47b5 Mon Sep 17 00:00:00 2001 From: xue <> Date: Fri, 7 Jul 2006 14:54:15 +0000 Subject: Merge from 3.0 branch till 1253. --- .../docs/en/expectation_documentation.html | 356 --------------------- 1 file changed, 356 deletions(-) delete mode 100644 tests/UnitTests/simpletest/docs/en/expectation_documentation.html (limited to 'tests/UnitTests/simpletest/docs/en/expectation_documentation.html') 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 @@ - - - - - Extending the SimpleTest unit tester with additional expectation classes - - - - - -

Expectation documentation

-
-

- -

More control over mock objects

- -

-

- The default behaviour of the - mock objects - in - SimpleTest - 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. -

-

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

-

- For example, suppose we have a news service that has failed - to connect to its remote source. -

-class NewsService {
-    ...
-    function publish(&$writer) {
-        if (! $this->isConnected()) {
-            $writer->write('Cannot connect to news service "' .
-                    $this->_name . '" at this time. ' .
-                    'Please try again later.');
-        }
-        ...
-    }
-}
-
- Here it is sending its content to a - Writer class. - We could test this behaviour with a - MockWriter like so... -
-class TestOfNewsService extends UnitTestCase {
-    ...
-    function testConnectionFailure() {
-        $writer = &new MockWriter($this);
-        $writer->expectOnce('write', array(
-                'Cannot connect to news service ' .
-                '"BBC News" at this time. ' .
-                'Please try again later.'));
-        
-        $service = &new NewsService('BBC News');
-        $service->publish($writer);
-        
-        $writer->tally();
-    }
-}
-
- 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. -

-

- To get around this, we would like to do a regular expression - test rather than an exact match. - We can actually do this with... -

-class TestOfNewsService extends UnitTestCase {
-    ...
-    function testConnectionFailure() {
-        $writer = &new MockWriter($this);
-        $writer->expectOnce(
-                'write',
-                array(new WantedPatternExpectation('/cannot connect/i')));
-        
-        $service = &new NewsService('BBC News');
-        $service->publish($writer);
-        
-        $writer->tally();
-    }
-}
-
- Instead of passing in the expected parameter to the - MockWriter we pass an - expectation class called - WantedPatternExpectation. - 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. -

-

- The WantedPatternExpectation takes - the regular expression to match in its constructor. - Whenever a comparison is made by the MockWriter - against this expectation class, it will do a - preg_match() 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. -

-

- The possible expectation classes are... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EqualExpectationAn equality, rather than the stronger identity comparison
NotEqualExpectationAn inequality comparison
IndenticalExpectationThe default mock object check which must match exactly
NotIndenticalExpectationInverts the mock object logic
WantedPatternExpectationUses a Perl Regex to match a string
NoUnwantedPatternExpectationPasses only if failing a Perl Regex
IsAExpectationChecks the type or class name only
NotAExpectationOpposite of the IsAExpectation
MethodExistsExpectationChecks a method is available on an object
- Most take the expected value in the constructor. - The exceptions are the pattern matchers, which take a regular expression, - and the IsAExpectation and NotAExpectation which takes a type - or class name as a string. -

- -

- -

Using expectations to control stubs

- -

-

- The expectation classes can be used not just for sending assertions - from mock objects, but also for selecting behaviour for either - the - mock objects - or the - server stubs. - Anywhere a list of arguments is given, a list of expectation objects - can be inserted instead. -

-

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

-Stub::generate('Authorisation');
-
-$authorisation = new StubAuthorisation();
-$authorisation->setReturnValue(
-        'isAllowed',
-        true,
-        array(new IsAExpectation('Session', 'Must be a session')));
-$authorisation->setReturnValue('isAllowed', false);
-
- We have set the default stub behaviour to return false when - isAllowed is called. - When we call the method with a single parameter that - is a Session 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. -

-

- This kind of sophistication is rarely useful, but is included for - completeness. -

- -

- -

Creating your own expectations

- -

-

- The expectation classes have a very simple structure. - So simple that it is easy to create your own versions for - commonly used test logic. -

-

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

-class ValidIp extends SimpleExpectation {
-    
-    function test($ip) {
-        return (ip2long($ip) != -1);
-    }
-    
-    function testMessage($ip) {
-        return "Address [$ip] should be a valid IP address";
-    }
-}
-
- There are only two methods to implement. - The test() method should - evaluate to true if the expectation is to pass, and - false otherwise. - The testMessage() method - should simply return some helpful text explaining the test - that was carried out. -

-

- This class can now be used in place of the earlier expectation - classes. -

- -

- -

Under the bonnet of the unit tester

- -

-

- The SimpleTest unit testing framework - also uses the expectation classes internally for the - UnitTestCase class. - We can also take advantage of these mechanisms to reuse our - homebrew expectation classes within the test suites directly. -

-

- The most crude way of doing this is to use the - SimpleTest::assertExpectation() method to - test against it directly... -

-class TestOfNetworking extends UnitTestCase {
-    ...
-    function testGetValidIp() {
-        $server = &new Server();
-        $this->assertExpectation(
-                new ValidIp(),
-                $server->getIp(),
-                'Server IP address->%s');
-    }
-}
-
- This is a little untidy compared with our usual - assert...() syntax. -

-

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

-class TestOfNetworking extends UnitTestCase {
-    ...
-    function assertValidIp($ip, $message = '%s') {
-        $this->assertExpectation(new ValidIp(), $ip, $message);
-    }
-    
-    function testGetValidIp() {
-        $server = &new Server();
-        $this->assertValidIp(
-                $server->getIp(),
-                'Server IP address->%s');
-    }
-}
-
- 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. -

- -
- - - -- cgit v1.2.3