diff options
author | wei <> | 2006-07-05 07:40:57 +0000 |
---|---|---|
committer | wei <> | 2006-07-05 07:40:57 +0000 |
commit | dfa5aa5fbf11f89ce483c58016465ddc3921f082 (patch) | |
tree | f01dd1c13d700b266695e503b3ebb6e05e591410 /test_tools/simpletest/docs/en/index.html | |
parent | b6dfb6c447cf502e694d299dbda1b2e092c3312d (diff) |
move to tests
Diffstat (limited to 'test_tools/simpletest/docs/en/index.html')
-rwxr-xr-x | test_tools/simpletest/docs/en/index.html | 467 |
1 files changed, 0 insertions, 467 deletions
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 @@ -<html> -<head> -<META http-equiv="Content-Type" content="text/html; charset=UTF-8"> -<title> - Download the Simple Test testing framework - - Unit tests and mock objects for PHP - </title> -<link rel="stylesheet" type="text/css" href="docs.css" title="Styles"> -</head> -<body> -<div class="menu_back"> -<div class="menu"> -<h2> -<span class="chosen">SimpleTest</span> -</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> -<a href="server_stubs_documentation.html">Server stubs</a> -</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>Simple Test for PHP</h1> -<div class="content"> - - - <p> - 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 - <a href="https://sourceforge.net/project/showfiles.php?group_id=76550">SimpleTest</a>. - For fuller documentation, especially if you are new - to unit testing see the ongoing - <a href="unit_test_documentation.html">documentation</a>, and for - example test cases see the - <a href="http://www.lastcraft.com/first_test_tutorial.php">unit testing tutorial</a>. - </p> - - <p> -<a class="target" name="unit"> -<h2>Using the tester quickly</h2> -</a> -</p> - <p> - 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 - <a href="http://www.junit.org/">JUnit</a> and the - <a href="http://sourceforge.net/projects/phpunit/">PHPUnit</a> - ports, but also adds - <a href="http://www.mockobjects.com">mock objects</a>. - It has some <a href="http://sourceforge.net/projects/jwebunit/">JWebUnit</a> - functionality as well. - This includes web page navigation, cookie testing and form submission. - </p> - <p> - The quickest way to demonstrate is with an example. - </p> - <p> - Let us suppose we are testing a simple file logging class called - <span class="new_code">Log</span> in <em>classes/log.php</em>. - 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 -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); -require_once('../classes/log.php'); -<strong> -class TestOfLogging extends UnitTestCase { -}</strong> -?> -</pre> - 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 - takes the file name to write to in the constructor and we have - a temporary folder in which to place this file... -<pre> -<?php -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); -require_once('../classes/log.php'); - -class TestOfLogging extends UnitTestCase { - <strong> - 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')); - }</strong> -} -?> -</pre> - When a test case runs it will search for any method that - starts with the string <span class="new_code">test</span> - 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 - <span class="new_code">print</span> statements can display - their content right next to the test case concerned. - </p> - <p> - 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... -<pre> -<?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')); - } -} -<strong> -$test = &new TestOfLogging(); -$test->run(new HtmlReporter());</strong> -?> -</pre> - </p> - <p> - On failure the display looks like this... - <div class="demo"> - <h1>testoflogging</h1> - <span class="fail">Fail</span>: testcreatingnewfile->True assertion failed.<br> - <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete. - <strong>1</strong> passes and <strong>1</strong> fails.</div> - </div> - ...and if it passes like this... - <div class="demo"> - <h1>testoflogging</h1> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. - <strong>2</strong> passes and <strong>0</strong> fails.</div> - </div> - And if you get this... - <div class="demo"> - <b>Fatal error</b>: Failed opening required '../classes/log.php' (include_path='') in <b>/home/marcus/projects/lastcraft/tutorial_tests/Log/tests/log_test.php</b> on line <b>7</b> - </div> - it means you're missing the <em>classes/Log.php</em> file that could look like... -<pre> -<?php -class Log { - - function Log($file_path) { - } - - function message() { - } -} -?>; -</pre> - </p> - - <p> -<a class="target" name="group"> -<h2>Building group tests</h2> -</a> -</p> - <p> - 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. - </p> - <p> - Our first step is to strip the includes and to undo our - previous hack... -<pre> -<?php<strong> -require_once('../classes/log.php');</strong> - -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'));<strong> - } -} -?></strong> -</pre> - Next we create a new file called <em>tests/all_tests.php</em> - and insert the following code... -<pre> -<strong><?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()); -?></strong> -</pre> - The method <span class="new_code">GroupTest::addTestFile()</span> - will include the test case file and read any new classes created - that are descended from <span class="new_code">SimpleTestCase</span>, of which - <span class="new_code">UnitTestCase</span> 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. - </p> - <p> - 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 <span class="new_code">SimpleTestOptions::ignore()</span> 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 <span class="new_code">GroupTest::addTestFile()</span> - method will not detect them. - </p> - <p> - To display the results it is necessary only to invoke - <em>tests/all_tests.php</em> from the web server. - </p> - - <p> -<a class="target" name="mock"> -<h2>Using mock objects</h2> -</a> -</p> - <p> - Let's move further into the future. - </p> - <p> - 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 - <span class="new_code">SessionPool</span>. - We want to test a method that will probably end up looking - like this... -<pre> -<strong> -class SessionPool { - ... - function logIn($username) { - ... - $this->_log->message("User $username logged in."); - ... - } - ... -} -</strong> -</pre> - In the spirit of reuse we are using our - <span class="new_code">Log</span> class. - A conventional test case might look like this... -<pre> -<strong> -<?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"); - } -} -?></strong> -</pre> - 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 <span class="new_code">Log</span> class and - this test. - What if we don't use files any more, but use ths - <em>syslog</em> 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? - </p> - <p> - 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. - </p> - <p> - 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. - <p> - </p> - Too good to be true? - Luckily we can create such an object easily... -<pre> -<?php -require_once('../classes/log.php'); -require_once('../classes/session_pool.php');<strong> -Mock::generate('Log');</strong> - -class TestOfSessionLogging extends UnitTestCase { - - function testLogInIsLogged() {<strong> - $log = &new MockLog($this); - $log->expectOnce('message', array('User fred logged in.'));</strong> - $session_pool = &new SessionPool($log); - $session_pool->logIn('fred');<strong> - $log->tally();</strong> - } -} -?> -</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 - <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 - resulting pass or fail event to the test display. - Wildcards can be included here too so as to prevent tests - becoming too specific. - </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 - parameter expectations and limits on the number of times - a method is to be invoked. - </p> - <p> - For this test to run the mock objects library must have been - included in the test suite, say in <em>all_tests.php</em>. - </p> - - <p> -<a class="target" name="web"> -<h2>Web page testing</h2> -</a> -</p> - <p> - 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. - </p> - <p> - 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. -<pre> -<?php<strong> -require_once('simpletest/web_tester.php');</strong> -require_once('simpletest/reporter.php'); -<strong> -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'); - } -}</strong> -$test = &new TestOfAbout(); -$test->run(new HtmlReporter()); -?> -</pre> - 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. - </p> - <p> - <a href="http://sourceforge.net/projects/simpletest/"><img src="http://sourceforge.net/sflogo.php?group_id=76550&type=5" width="210" height="62" border="0" alt="SourceForge.net Logo"></a> - </p> - - </div> -<div class="copyright"> - Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004 - </div> -</body> -</html> |