From dfa5aa5fbf11f89ce483c58016465ddc3921f082 Mon Sep 17 00:00:00 2001 From: wei <> Date: Wed, 5 Jul 2006 07:40:57 +0000 Subject: move to tests --- test_tools/simpletest/docs/en/index.html | 467 ------------------------------- 1 file changed, 467 deletions(-) delete mode 100755 test_tools/simpletest/docs/en/index.html (limited to 'test_tools/simpletest/docs/en/index.html') diff --git a/test_tools/simpletest/docs/en/index.html b/test_tools/simpletest/docs/en/index.html deleted file mode 100755 index 04797272..00000000 --- a/test_tools/simpletest/docs/en/index.html +++ /dev/null @@ -1,467 +0,0 @@ - - - - - Download the Simple Test testing framework - - Unit tests and mock objects for PHP - - - - - -

Simple Test for PHP

-
- - -

- 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 - SimpleTest. - For fuller documentation, especially if you are new - to unit testing see the ongoing - documentation, and for - example test cases see the - unit testing tutorial. -

- -

- -

Using the tester quickly

- -

-

- 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 - JUnit and the - PHPUnit - ports, but also adds - mock objects. - It has some JWebUnit - functionality as well. - This includes web page navigation, cookie testing and form submission. -

-

- The quickest way to demonstrate is with an example. -

-

- Let us suppose we are testing a simple file logging class called - Log in classes/log.php. - We start by creating a test script which we will call - tests/log_test.php and populate it as follows... -

-<?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-?>
-
- Here the simpletest 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... -
-<?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-require_once('../classes/log.php');
-
-class TestOfLogging extends UnitTestCase {
-}
-?>
-
- 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 Log class - takes the file name to write to in the constructor and we have - a temporary folder in which to place this file... -
-<?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->assertFalse(file_exists('/temp/test.log'));
-        $log->message('Should write this to a file');
-        $this->assertTrue(file_exists('/temp/test.log'));
-    }
-}
-?>
-
- When a test case runs it will search for any method that - starts with the string test - 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 - print statements can display - their content right next to the test case concerned. -

-

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

-<?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->assertFalse(file_exists('/temp/test.log'));
-        $log->message('Should write this to a file');
-        $this->assertTrue(file_exists('/temp/test.log'));
-    }
-}
-
-$test = &new TestOfLogging();
-$test->run(new HtmlReporter());
-?>
-
-

-

- On failure the display looks like this... -

-

testoflogging

- Fail: testcreatingnewfile->True assertion failed.
-
1/1 test cases complete. - 1 passes and 1 fails.
-
- ...and if it passes like this... -
-

testoflogging

-
1/1 test cases complete. - 2 passes and 0 fails.
-
- And if you get this... -
- Fatal error: Failed opening required '../classes/log.php' (include_path='') in /home/marcus/projects/lastcraft/tutorial_tests/Log/tests/log_test.php on line 7 -
- it means you're missing the classes/Log.php file that could look like... -
-<?php
-class Log {
-    
-        function Log($file_path) {
-        }
-
-		function message() {
-		}
-}
-?>;
-
-

- -

- -

Building group tests

- -

-

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

-

- Our first step is to strip the includes and to undo our - previous hack... -

-<?php
-require_once('../classes/log.php');
-
-class TestOfLogging extends UnitTestCase {
-    
-    function testCreatingNewFile() {
-        @unlink('/temp/test.log');
-        $log = new Log('/temp/test.log');
-        $this->assertFalse(file_exists('/temp/test.log'));
-        $log->message('Should write this to a file');
-        $this->assertTrue(file_exists('/temp/test.log'));
-    }
-}
-?>
-
- Next we create a new file called tests/all_tests.php - and insert the following code... -
-<?php
-require_once('simpletest/unit_tester.php');
-require_once('simpletest/reporter.php');
-
-$test = &new GroupTest('All tests');
-$test->addTestFile('log_test.php');
-$test->run(new HtmlReporter());
-?>
-
- The method GroupTest::addTestFile() - will include the test case file and read any new classes created - that are descended from SimpleTestCase, of which - UnitTestCase 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. -

-

- 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 SimpleTestOptions::ignore() 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 GroupTest::addTestFile() - method will not detect them. -

-

- To display the results it is necessary only to invoke - tests/all_tests.php from the web server. -

- -

- -

Using mock objects

- -

-

- Let's move further into the future. -

-

- 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 - SessionPool. - We want to test a method that will probably end up looking - like this... -

-
-class SessionPool {
-    ...
-    function logIn($username) {
-        ...
-        $this->_log->message("User $username logged in.");
-        ...
-    }
-    ...
-}
-
-
- In the spirit of reuse we are using our - Log class. - A conventional test case might look like this... -
-
-<?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 = &new SessionPool($log);
-        $session_pool->logIn('fred');
-        $messages = file('/temp/test.log');
-        $this->assertEqual($messages[0], "User fred logged in.\n");
-    }
-}
-?>
-
- 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 Log class and - this test. - What if we don't use files any more, but use ths - syslog 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? -

-

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

-

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

-

- Too good to be true? - Luckily we can create such an object easily... -
-<?php
-require_once('../classes/log.php');
-require_once('../classes/session_pool.php');
-Mock::generate('Log');
-
-class TestOfSessionLogging extends UnitTestCase {
-    
-    function testLogInIsLogged() {
-        $log = &new MockLog($this);
-        $log->expectOnce('message', array('User fred logged in.'));
-        $session_pool = &new SessionPool($log);
-        $session_pool->logIn('fred');
-        $log->tally();
-    }
-}
-?>
-
- The tally() 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 - message() is invoked on the - MockLog 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. -

-

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

-

- For this test to run the mock objects library must have been - included in the test suite, say in all_tests.php. -

- -

- -

Web page testing

- -

-

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

-

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

-<?php
-require_once('simpletest/web_tester.php');
-require_once('simpletest/reporter.php');
-
-class TestOfAbout extends WebTestCase {
-    
-    function setUp() {
-        $this->get('http://test-server/index.php');
-        $this->clickLink('About');
-    }
-    
-    function testSearchEngineOptimisations() {
-        $this->assertTitle('A long title about us for search engines');
-        $this->assertWantedPattern('/a popular keyphrase/i');
-    }
-}
-$test = &new TestOfAbout();
-$test->run(new HtmlReporter());
-?>
-
- 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. -

-

- SourceForge.net Logo -

- -
- - - -- cgit v1.2.3