Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Right-click on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(39) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(20) |
Feb
(8) |
Mar
(22) |
Apr
(14) |
May
(48) |
Jun
(29) |
Jul
(48) |
Aug
(5) |
Sep
(13) |
Oct
(5) |
Nov
(28) |
Dec
(42) |
2008 |
Jan
(32) |
Feb
(39) |
Mar
(60) |
Apr
(117) |
May
(9) |
Jun
(35) |
Jul
(1) |
Aug
(11) |
Sep
(38) |
Oct
(26) |
Nov
(7) |
Dec
(65) |
2009 |
Jan
(30) |
Feb
(22) |
Mar
(9) |
Apr
(5) |
May
(10) |
Jun
(13) |
Jul
(60) |
Aug
(9) |
Sep
(24) |
Oct
(20) |
Nov
(20) |
Dec
(28) |
2010 |
Jan
|
Feb
|
Mar
(11) |
Apr
(19) |
May
(7) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
|
Oct
(8) |
Nov
(8) |
Dec
(4) |
2011 |
Jan
|
Feb
(1) |
Mar
(3) |
Apr
(22) |
May
(7) |
Jun
(20) |
Jul
(6) |
Aug
(4) |
Sep
|
Oct
(1) |
Nov
(13) |
Dec
(4) |
2012 |
Jan
(14) |
Feb
|
Mar
(4) |
Apr
(14) |
May
(3) |
Jun
(4) |
Jul
(3) |
Aug
(1) |
Sep
(2) |
Oct
(4) |
Nov
(5) |
Dec
(2) |
2013 |
Jan
(1) |
Feb
(3) |
Mar
|
Apr
(1) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
(9) |
10
(1) |
11
|
12
(2) |
13
|
14
(2) |
15
|
16
(3) |
17
|
18
(3) |
19
(3) |
20
|
21
|
22
(1) |
23
(1) |
24
|
25
(3) |
26
(6) |
27
(2) |
28
(3) |
29
|
|
From: <pp11@us...> - 2008-02-28 21:09:45
|
Revision: 1663 http://simpletest.svn.sourceforge.net/simpletest/?rev=1663&view=rev Author: pp11 Date: 2008-02-28 13:09:41 -0800 (Thu, 28 Feb 2008) Log Message: ----------- Adding a small comment about "$mocked->expectAt(0, 'method', 'args);" Modified Paths: -------------- simpletest/trunk/docs/source/en/mock_objects_documentation.xml Modified: simpletest/trunk/docs/source/en/mock_objects_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/mock_objects_documentation.xml 2008-02-28 20:47:27 UTC (rev 1662) +++ simpletest/trunk/docs/source/en/mock_objects_documentation.xml 2008-02-28 21:09:41 UTC (rev 1663) @@ -566,6 +566,14 @@ It is silent if the limit is never reached. </p> <p> + Also if you have juste one call in your test, make sure you're using + <code>expectOnce</code>.<br /> + Using <code>$mocked->expectAt(0, 'method', 'args);</code> + on its own will not be catched : + checking the arguments and the overall call count + are currently independant. + </p> + <p> Like the assertions within test cases, all of the expectations can take a message override as an extra parameter. Also the original failure message can be embedded in the output This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: SourceForge.net <noreply@so...> - 2008-02-28 20:52:56
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by pp11 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Closed Resolution: Accepted Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Perrick Penet (pp11) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: Perrick Penet (pp11) Date: 2008-02-28 21:52 Message: Logged In: YES user_id=292377 Originator: NO Thanks for the tip. I added a small comment regarding this stuff. By the way, the documentation is going through a major rewrite (autorun is the way). If you want you can have a look at it : http://simpletest.org/1.0.1RC1/en/start-testing.html All feedback is very welcomed... Yours, Perrick ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-27 11:06 Message: Logged In: YES user_id=663176 Originator: YES Great. You might want to update the documentation at http://simpletest.org/en/group_test_documentation.html, which currently says: """ There are two things that could go wrong and which require care... 1. The file could already have been parsed by PHP, and so no new classes will have been added. You should make sure that the test cases are only included in this file and no others. """ ..this should be fixed by this patch. ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-26 22:06 Message: Logged In: YES user_id=292377 Originator: NO Thanks again for both the patch and the test. It's been applied to the SVN trunk. Yours, Perrick ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 12:51 Message: Logged In: YES user_id=663176 Originator: YES It actually works also from the browser.. The problem has been that the "support/test1.php" file wasn't copied to the system where I've tested it with the browser.. and the "require_once"-error has been suppressed. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 09:03 Message: Logged In: YES user_id=663176 Originator: YES Well, the test only works if called with "php -f" from the command line, but not from the browser, where it says: test_load_if_included.php Fail: -> Bad TestSuite [test_load_if_included.php] with error [No runnable test cases in [test_load_if_included.php]] 0/0 test cases complete: 0 passes, 1 fails and 0 exceptions. I think you can figure this out better than me and integrate it properly in the existing tests. Thank you. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: <pp11@us...> - 2008-02-28 20:47:31
|
Revision: 1662 http://simpletest.svn.sourceforge.net/simpletest/?rev=1662&view=rev Author: pp11 Date: 2008-02-28 12:47:27 -0800 (Thu, 28 Feb 2008) Log Message: ----------- Adding a comment on grouping tests (following patch n?\194?\1761899780 by daniel hahler - blueyed) Modified Paths: -------------- simpletest/trunk/docs/source/en/group_test_documentation.xml Modified: simpletest/trunk/docs/source/en/group_test_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/group_test_documentation.xml 2008-02-26 21:04:31 UTC (rev 1661) +++ simpletest/trunk/docs/source/en/group_test_documentation.xml 2008-02-28 20:47:27 UTC (rev 1662) @@ -120,10 +120,11 @@ There are two things that could go wrong and which require care... <ol> <li> - The file could already have been parsed by PHP, and so no + The file could already have been parsed by PHP, and so no new classes will have been added. You should make sure that the test cases are only included in this file - and no others. + and no others (Note : with the new <cite>autorun</cite> + functionnality, this problem has now been solved). </li> <li> New test case extension classes that get included will be This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: SourceForge.net <noreply@so...> - 2008-02-27 10:49:53
|
Patches item #1902180, was opened at 2008-02-26 15:29 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Closed Resolution: Rejected Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Perrick Penet (pp11) Summary: autorun.php: configure Reporter to use Initial Comment: The attached patch allows configuration of the Reporter to use in autorun.php: If the global $AUTORUN_REPORTER is set, it's used instead of the DefaultReporter. This is useful when using autorun.php, which is really convenient, but you want to use e.g. an own ShowPassesReporter. ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-27 11:49 Message: Logged In: YES user_id=663176 Originator: YES SimpleTest::prefer() is what I was looking for, much better than my proposed patch. Thank you. ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-26 22:15 Message: Logged In: YES user_id=292377 Originator: NO Well there's already a "SimpleTest :: prefer(new HtmlReporter());" to do this sort of stuff. Have you tried using it ? You can find out more about it insided the documentation : http://simpletest.org/en/experimental_autorun.html#preference It's now part of the core and the "experimental" tag will be stripped out with the next release so it should alreay be stable ! Yours, Perrick PS : I've put "rejected" in the resolution and "pending" in the status. That way the patch request will closed itselft down after 2 weeks. Unless you re-open it ! ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-26 15:30 Message: Logged In: YES user_id=663176 Originator: YES File Added: simpletest-autorun-configure-reporter-plus-whitespace.diff ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-27 10:06:59
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Closed Resolution: Accepted Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Perrick Penet (pp11) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-27 11:06 Message: Logged In: YES user_id=663176 Originator: YES Great. You might want to update the documentation at http://simpletest.org/en/group_test_documentation.html, which currently says: """ There are two things that could go wrong and which require care... 1. The file could already have been parsed by PHP, and so no new classes will have been added. You should make sure that the test cases are only included in this file and no others. """ ..this should be fixed by this patch. ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-26 22:06 Message: Logged In: YES user_id=292377 Originator: NO Thanks again for both the patch and the test. It's been applied to the SVN trunk. Yours, Perrick ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 12:51 Message: Logged In: YES user_id=663176 Originator: YES It actually works also from the browser.. The problem has been that the "support/test1.php" file wasn't copied to the system where I've tested it with the browser.. and the "require_once"-error has been suppressed. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 09:03 Message: Logged In: YES user_id=663176 Originator: YES Well, the test only works if called with "php -f" from the command line, but not from the browser, where it says: test_load_if_included.php Fail: -> Bad TestSuite [test_load_if_included.php] with error [No runnable test cases in [test_load_if_included.php]] 0/0 test cases complete: 0 passes, 1 fails and 0 exceptions. I think you can figure this out better than me and integrate it properly in the existing tests. Thank you. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-26 21:15:24
|
Patches item #1902180, was opened at 2008-02-26 15:29 Message generated for change (Comment added) made by pp11 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Pending >Resolution: Rejected Priority: 5 Private: No Submitted By: daniel hahler (blueyed) >Assigned to: Perrick Penet (pp11) Summary: autorun.php: configure Reporter to use Initial Comment: The attached patch allows configuration of the Reporter to use in autorun.php: If the global $AUTORUN_REPORTER is set, it's used instead of the DefaultReporter. This is useful when using autorun.php, which is really convenient, but you want to use e.g. an own ShowPassesReporter. ---------------------------------------------------------------------- >Comment By: Perrick Penet (pp11) Date: 2008-02-26 22:15 Message: Logged In: YES user_id=292377 Originator: NO Well there's already a "SimpleTest :: prefer(new HtmlReporter());" to do this sort of stuff. Have you tried using it ? You can find out more about it insided the documentation : http://simpletest.org/en/experimental_autorun.html#preference It's now part of the core and the "experimental" tag will be stripped out with the next release so it should alreay be stable ! Yours, Perrick PS : I've put "rejected" in the resolution and "pending" in the status. That way the patch request will closed itselft down after 2 weeks. Unless you re-open it ! ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-26 15:30 Message: Logged In: YES user_id=663176 Originator: YES File Added: simpletest-autorun-configure-reporter-plus-whitespace.diff ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-26 21:06:58
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by pp11 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Closed >Resolution: Accepted Priority: 5 Private: No Submitted By: daniel hahler (blueyed) >Assigned to: Perrick Penet (pp11) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: Perrick Penet (pp11) Date: 2008-02-26 22:06 Message: Logged In: YES user_id=292377 Originator: NO Thanks again for both the patch and the test. It's been applied to the SVN trunk. Yours, Perrick ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 12:51 Message: Logged In: YES user_id=663176 Originator: YES It actually works also from the browser.. The problem has been that the "support/test1.php" file wasn't copied to the system where I've tested it with the browser.. and the "require_once"-error has been suppressed. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 09:03 Message: Logged In: YES user_id=663176 Originator: YES Well, the test only works if called with "php -f" from the command line, but not from the browser, where it says: test_load_if_included.php Fail: -> Bad TestSuite [test_load_if_included.php] with error [No runnable test cases in [test_load_if_included.php]] 0/0 test cases complete: 0 passes, 1 fails and 0 exceptions. I think you can figure this out better than me and integrate it properly in the existing tests. Thank you. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: <pp11@us...> - 2008-02-26 21:04:44
|
Revision: 1661 http://simpletest.svn.sourceforge.net/simpletest/?rev=1661&view=rev Author: pp11 Date: 2008-02-26 13:04:31 -0800 (Tue, 26 Feb 2008) Log Message: ----------- Applying pach [ 1899780 ] SimpleFileLoader::load: fix for $test_file already included, by daniel hahler - blueyed Modified Paths: -------------- simpletest/trunk/test/unit_tests.php simpletest/trunk/test_case.php Added Paths: ----------- simpletest/trunk/test/autorun_test.php Added: simpletest/trunk/test/autorun_test.php =================================================================== --- simpletest/trunk/test/autorun_test.php (rev 0) +++ simpletest/trunk/test/autorun_test.php 2008-02-26 21:04:31 UTC (rev 1661) @@ -0,0 +1,13 @@ +<?php +require_once(dirname(__FILE__) . '/../autorun.php'); +require_once(dirname(__FILE__) . '/support/test1.php'); + +class LoadIfIncludedTestCase extends UnitTestCase { + function test_load_if_included() { + $tests = new GroupTest(); + $tests->addFile(dirname(__FILE__) . '/support/test1.php'); + $this->assertEqual($tests->getSize(), 1); + } +} + +?> \ No newline at end of file Modified: simpletest/trunk/test/unit_tests.php =================================================================== --- simpletest/trunk/test/unit_tests.php 2008-02-26 20:41:25 UTC (rev 1660) +++ simpletest/trunk/test/unit_tests.php 2008-02-26 21:04:31 UTC (rev 1661) @@ -16,6 +16,7 @@ if (version_compare(phpversion(), '5') >= 0) { $this->addFile($path . '/exceptions_test.php'); } + $this->addFile($path . '/autorun_test.php'); $this->addFile($path . '/compatibility_test.php'); $this->addFile($path . '/simpletest_test.php'); $this->addFile($path . '/dumper_test.php'); Modified: simpletest/trunk/test_case.php =================================================================== --- simpletest/trunk/test_case.php 2008-02-26 20:41:25 UTC (rev 1660) +++ simpletest/trunk/test_case.php 2008-02-26 21:04:31 UTC (rev 1661) @@ -1,670 +1,677 @@ <?php +/** + * Base include file for SimpleTest + * @package SimpleTest + * @subpackage UnitTester + * @version $Id$ + */ + +/**#@+ + * Includes SimpleTest files and defined the root constant + * for dependent libraries. + */ +require_once(dirname(__FILE__) . '/invoker.php'); +require_once(dirname(__FILE__) . '/errors.php'); +require_once(dirname(__FILE__) . '/compatibility.php'); +require_once(dirname(__FILE__) . '/scorer.php'); +require_once(dirname(__FILE__) . '/expectation.php'); +require_once(dirname(__FILE__) . '/dumper.php'); +require_once(dirname(__FILE__) . '/simpletest.php'); +if (version_compare(phpversion(), '5') >= 0) { + require_once(dirname(__FILE__) . '/exceptions.php'); + require_once(dirname(__FILE__) . '/reflection_php5.php'); +} else { + require_once(dirname(__FILE__) . '/reflection_php4.php'); +} +if (! defined('SIMPLE_TEST')) { /** - * Base include file for SimpleTest - * @package SimpleTest - * @subpackage UnitTester - * @version $Id$ + * @ignore */ + define('SIMPLE_TEST', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} +/**#@-*/ - /**#@+ - * Includes SimpleTest files and defined the root constant - * for dependent libraries. +/** + * Basic test case. This is the smallest unit of a test + * suite. It searches for + * all methods that start with the the string "test" and + * runs them. Working test cases extend this class. + * @package SimpleTest + * @subpackage UnitTester + */ +class SimpleTestCase { + var $_label = false; + var $_reporter; + var $_observers; + var $_should_skip = false; + + /** + * Sets up the test with no display. + * @param string $label If no test name is given then + * the class name is used. + * @access public */ - require_once(dirname(__FILE__) . '/invoker.php'); - require_once(dirname(__FILE__) . '/errors.php'); - require_once(dirname(__FILE__) . '/compatibility.php'); - require_once(dirname(__FILE__) . '/scorer.php'); - require_once(dirname(__FILE__) . '/expectation.php'); - require_once(dirname(__FILE__) . '/dumper.php'); - require_once(dirname(__FILE__) . '/simpletest.php'); - if (version_compare(phpversion(), '5') >= 0) { - require_once(dirname(__FILE__) . '/exceptions.php'); - require_once(dirname(__FILE__) . '/reflection_php5.php'); - } else { - require_once(dirname(__FILE__) . '/reflection_php4.php'); + function SimpleTestCase($label = false) { + if ($label) { + $this->_label = $label; + } } - if (! defined('SIMPLE_TEST')) { - /** - * @ignore - */ - define('SIMPLE_TEST', dirname(__FILE__) . DIRECTORY_SEPARATOR); + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label ? $this->_label : get_class($this); } - /**#@-*/ /** - * Basic test case. This is the smallest unit of a test - * suite. It searches for - * all methods that start with the the string "test" and - * runs them. Working test cases extend this class. - * @package SimpleTest - * @subpackage UnitTester + * This is a placeholder for skipping tests. In this + * method you place skipIf() and skipUnless() calls to + * set the skipping state. + * @access public */ - class SimpleTestCase { - var $_label = false; - var $_reporter; - var $_observers; - var $_should_skip = false; + function skip() { + } - /** - * Sets up the test with no display. - * @param string $label If no test name is given then - * the class name is used. - * @access public - */ - function SimpleTestCase($label = false) { - if ($label) { - $this->_label = $label; - } - } + /** + * Will issue a message to the reporter and tell the test + * case to skip if the incoming flag is true. + * @param string $should_skip Condition causing the tests to be skipped. + * @param string $message Text of skip condition. + * @access public + */ + function skipIf($should_skip, $message = '%s') { + if ($should_skip && ! $this->_should_skip) { + $this->_should_skip = true; + $message = sprintf($message, 'Skipping [' . get_class($this) . ']'); + $this->_reporter->paintSkip($message . $this->getAssertionLine()); + } + } - /** - * Accessor for the test name for subclasses. - * @return string Name of the test. - * @access public - */ - function getLabel() { - return $this->_label ? $this->_label : get_class($this); - } + /** + * Will issue a message to the reporter and tell the test + * case to skip if the incoming flag is false. + * @param string $shouldnt_skip Condition causing the tests to be run. + * @param string $message Text of skip condition. + * @access public + */ + function skipUnless($shouldnt_skip, $message = false) { + $this->skipIf(! $shouldnt_skip, $message); + } - /** - * This is a placeholder for skipping tests. In this - * method you place skipIf() and skipUnless() calls to - * set the skipping state. - * @access public - */ - function skip() { + /** + * Used to invoke the single tests. + * @return SimpleInvoker Individual test runner. + * @access public + */ + function &createInvoker() { + $invoker = &new SimpleErrorTrappingInvoker(new SimpleInvoker($this)); + if (version_compare(phpversion(), '5') >= 0) { + $invoker = &new SimpleExceptionTrappingInvoker($invoker); } + return $invoker; + } - /** - * Will issue a message to the reporter and tell the test - * case to skip if the incoming flag is true. - * @param string $should_skip Condition causing the tests to be skipped. - * @param string $message Text of skip condition. - * @access public - */ - function skipIf($should_skip, $message = '%s') { - if ($should_skip && ! $this->_should_skip) { - $this->_should_skip = true; - $message = sprintf($message, 'Skipping [' . get_class($this) . ']'); - $this->_reporter->paintSkip($message . $this->getAssertionLine()); - } - } - - /** - * Will issue a message to the reporter and tell the test - * case to skip if the incoming flag is false. - * @param string $shouldnt_skip Condition causing the tests to be run. - * @param string $message Text of skip condition. - * @access public - */ - function skipUnless($shouldnt_skip, $message = false) { - $this->skipIf(! $shouldnt_skip, $message); - } - - /** - * Used to invoke the single tests. - * @return SimpleInvoker Individual test runner. - * @access public - */ - function &createInvoker() { - $invoker = &new SimpleErrorTrappingInvoker(new SimpleInvoker($this)); - if (version_compare(phpversion(), '5') >= 0) { - $invoker = &new SimpleExceptionTrappingInvoker($invoker); - } - return $invoker; - } - - /** - * Uses reflection to run every method within itself - * starting with the string "test" unless a method - * is specified. - * @param SimpleReporter $reporter Current test reporter. - * @return boolean True if all tests passed. - * @access public - */ - function run(&$reporter) { - $context = &SimpleTest::getContext(); - $context->setTest($this); - $context->setReporter($reporter); - $this->_reporter = &$reporter; - $started = false; - foreach ($this->getTests() as $method) { - if ($reporter->shouldInvoke($this->getLabel(), $method)) { - $this->skip(); - if ($this->_should_skip) { - break; - } - if (! $started) { - $reporter->paintCaseStart($this->getLabel()); - $started = true; - } - $invoker = &$this->_reporter->createInvoker($this->createInvoker()); - $invoker->before($method); - $invoker->invoke($method); - $invoker->after($method); + /** + * Uses reflection to run every method within itself + * starting with the string "test" unless a method + * is specified. + * @param SimpleReporter $reporter Current test reporter. + * @return boolean True if all tests passed. + * @access public + */ + function run(&$reporter) { + $context = &SimpleTest::getContext(); + $context->setTest($this); + $context->setReporter($reporter); + $this->_reporter = &$reporter; + $started = false; + foreach ($this->getTests() as $method) { + if ($reporter->shouldInvoke($this->getLabel(), $method)) { + $this->skip(); + if ($this->_should_skip) { + break; } - } - if ($started) { - $reporter->paintCaseEnd($this->getLabel()); - } - unset($this->_reporter); - return $reporter->getStatus(); - } - - /** - * Gets a list of test names. Normally that will - * be all internal methods that start with the - * name "test". This method should be overridden - * if you want a different rule. - * @return array List of test names. - * @access public - */ - function getTests() { - $methods = array(); - foreach (get_class_methods(get_class($this)) as $method) { - if ($this->_isTest($method)) { - $methods[] = $method; + if (! $started) { + $reporter->paintCaseStart($this->getLabel()); + $started = true; } + $invoker = &$this->_reporter->createInvoker($this->createInvoker()); + $invoker->before($method); + $invoker->invoke($method); + $invoker->after($method); } - return $methods; } + if ($started) { + $reporter->paintCaseEnd($this->getLabel()); + } + unset($this->_reporter); + return $reporter->getStatus(); + } - /** - * Tests to see if the method is a test that should - * be run. Currently any method that starts with 'test' - * is a candidate unless it is the constructor. - * @param string $method Method name to try. - * @return boolean True if test method. - * @access protected - */ - function _isTest($method) { - if (strtolower(substr($method, 0, 4)) == 'test') { - return ! SimpleTestCompatibility::isA($this, strtolower($method)); + /** + * Gets a list of test names. Normally that will + * be all internal methods that start with the + * name "test". This method should be overridden + * if you want a different rule. + * @return array List of test names. + * @access public + */ + function getTests() { + $methods = array(); + foreach (get_class_methods(get_class($this)) as $method) { + if ($this->_isTest($method)) { + $methods[] = $method; } - return false; } + return $methods; + } - /** - * Announces the start of the test. - * @param string $method Test method just started. - * @access public - */ - function before($method) { - $this->_reporter->paintMethodStart($method); - $this->_observers = array(); + /** + * Tests to see if the method is a test that should + * be run. Currently any method that starts with 'test' + * is a candidate unless it is the constructor. + * @param string $method Method name to try. + * @return boolean True if test method. + * @access protected + */ + function _isTest($method) { + if (strtolower(substr($method, 0, 4)) == 'test') { + return ! SimpleTestCompatibility::isA($this, strtolower($method)); } + return false; + } - /** - * Sets up unit test wide variables at the start - * of each test method. To be overridden in - * actual user test cases. - * @access public - */ - function setUp() { - } + /** + * Announces the start of the test. + * @param string $method Test method just started. + * @access public + */ + function before($method) { + $this->_reporter->paintMethodStart($method); + $this->_observers = array(); + } - /** - * Clears the data set in the setUp() method call. - * To be overridden by the user in actual user test cases. - * @access public - */ - function tearDown() { - } + /** + * Sets up unit test wide variables at the start + * of each test method. To be overridden in + * actual user test cases. + * @access public + */ + function setUp() { + } - /** - * Announces the end of the test. Includes private clean up. - * @param string $method Test method just finished. - * @access public - */ - function after($method) { - for ($i = 0; $i < count($this->_observers); $i++) { - $this->_observers[$i]->atTestEnd($method, $this); - } - $this->_reporter->paintMethodEnd($method); - } + /** + * Clears the data set in the setUp() method call. + * To be overridden by the user in actual user test cases. + * @access public + */ + function tearDown() { + } - /** - * Sets up an observer for the test end. - * @param object $observer Must have atTestEnd() - * method. - * @access public - */ - function tell(&$observer) { - $this->_observers[] = &$observer; + /** + * Announces the end of the test. Includes private clean up. + * @param string $method Test method just finished. + * @access public + */ + function after($method) { + for ($i = 0; $i < count($this->_observers); $i++) { + $this->_observers[$i]->atTestEnd($method, $this); } + $this->_reporter->paintMethodEnd($method); + } - /** - * @deprecated - */ - function pass($message = "Pass") { - if (! isset($this->_reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->_reporter->paintPass( - $message . $this->getAssertionLine()); - return true; - } + /** + * Sets up an observer for the test end. + * @param object $observer Must have atTestEnd() + * method. + * @access public + */ + function tell(&$observer) { + $this->_observers[] = &$observer; + } - /** - * Sends a fail event with a message. - * @param string $message Message to send. - * @access public - */ - function fail($message = "Fail") { - if (! isset($this->_reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->_reporter->paintFail( - $message . $this->getAssertionLine()); - return false; + /** + * @deprecated + */ + function pass($message = "Pass") { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); } + $this->_reporter->paintPass( + $message . $this->getAssertionLine()); + return true; + } - /** - * Formats a PHP error and dispatches it to the - * reporter. - * @param integer $severity PHP error code. - * @param string $message Text of error. - * @param string $file File error occoured in. - * @param integer $line Line number of error. - * @access public - */ - function error($severity, $message, $file, $line) { - if (! isset($this->_reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->_reporter->paintError( - "Unexpected PHP error [$message] severity [$severity] in [$file line $line]"); + /** + * Sends a fail event with a message. + * @param string $message Message to send. + * @access public + */ + function fail($message = "Fail") { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); } + $this->_reporter->paintFail( + $message . $this->getAssertionLine()); + return false; + } - /** - * Formats an exception and dispatches it to the - * reporter. - * @param Exception $exception Object thrown. - * @access public - */ - function exception($exception) { - $this->_reporter->paintException($exception); + /** + * Formats a PHP error and dispatches it to the + * reporter. + * @param integer $severity PHP error code. + * @param string $message Text of error. + * @param string $file File error occoured in. + * @param integer $line Line number of error. + * @access public + */ + function error($severity, $message, $file, $line) { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); } + $this->_reporter->paintError( + "Unexpected PHP error [$message] severity [$severity] in [$file line $line]"); + } - /** - * @deprecated - */ - function signal($type, &$payload) { - if (! isset($this->_reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->_reporter->paintSignal($type, $payload); - } + /** + * Formats an exception and dispatches it to the + * reporter. + * @param Exception $exception Object thrown. + * @access public + */ + function exception($exception) { + $this->_reporter->paintException($exception); + } - /** - * Runs an expectation directly, for extending the - * tests with new expectation classes. - * @param SimpleExpectation $expectation Expectation subclass. - * @param mixed $compare Value to compare. - * @param string $message Message to display. - * @return boolean True on pass - * @access public - */ - function assert(&$expectation, $compare, $message = '%s') { - if ($expectation->test($compare)) { - return $this->pass(sprintf( - $message, - $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); - } else { - return $this->fail(sprintf( - $message, - $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); - } + /** + * @deprecated + */ + function signal($type, &$payload) { + if (! isset($this->_reporter)) { + trigger_error('Can only make assertions within test methods'); } + $this->_reporter->paintSignal($type, $payload); + } - /** - * @deprecated - */ - function assertExpectation(&$expectation, $compare, $message = '%s') { - return $this->assert($expectation, $compare, $message); + /** + * Runs an expectation directly, for extending the + * tests with new expectation classes. + * @param SimpleExpectation $expectation Expectation subclass. + * @param mixed $compare Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assert(&$expectation, $compare, $message = '%s') { + if ($expectation->test($compare)) { + return $this->pass(sprintf( + $message, + $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); + } else { + return $this->fail(sprintf( + $message, + $expectation->overlayMessage($compare, $this->_reporter->getDumper()))); } + } - /** - * Uses a stack trace to find the line of an assertion. - * @return string Line number of first assert* - * method embedded in format string. - * @access public - */ - function getAssertionLine() { - $trace = new SimpleStackTrace(array('assert', 'expect', 'pass', 'fail', 'skip')); - return $trace->traceMethod(); - } + /** + * @deprecated + */ + function assertExpectation(&$expectation, $compare, $message = '%s') { + return $this->assert($expectation, $compare, $message); + } - /** - * Sends a formatted dump of a variable to the - * test suite for those emergency debugging - * situations. - * @param mixed $variable Variable to display. - * @param string $message Message to display. - * @return mixed The original variable. - * @access public - */ - function dump($variable, $message = false) { - $dumper = $this->_reporter->getDumper(); - $formatted = $dumper->dump($variable); - if ($message) { - $formatted = $message . "\n" . $formatted; - } - $this->_reporter->paintFormattedMessage($formatted); - return $variable; - } + /** + * Uses a stack trace to find the line of an assertion. + * @return string Line number of first assert* + * method embedded in format string. + * @access public + */ + function getAssertionLine() { + $trace = new SimpleStackTrace(array('assert', 'expect', 'pass', 'fail', 'skip')); + return $trace->traceMethod(); + } - /** - * @deprecated - */ - function sendMessage($message) { - $this->_reporter->PaintMessage($message); + /** + * Sends a formatted dump of a variable to the + * test suite for those emergency debugging + * situations. + * @param mixed $variable Variable to display. + * @param string $message Message to display. + * @return mixed The original variable. + * @access public + */ + function dump($variable, $message = false) { + $dumper = $this->_reporter->getDumper(); + $formatted = $dumper->dump($variable); + if ($message) { + $formatted = $message . "\n" . $formatted; } + $this->_reporter->paintFormattedMessage($formatted); + return $variable; + } - /** - * Accessor for the number of subtests. - * @return integer Number of test cases. - * @access public - * @static - */ - function getSize() { - return 1; - } + /** + * @deprecated + */ + function sendMessage($message) { + $this->_reporter->PaintMessage($message); } /** - * Helps to extract test cases automatically from a file. + * Accessor for the number of subtests. + * @return integer Number of test cases. + * @access public + * @static */ - class SimpleFileLoader { + function getSize() { + return 1; + } +} - /** - * Builds a test suite from a library of test cases. - * The new suite is composed into this one. - * @param string $test_file File name of library with - * test case classes. - * @return TestSuite The new test suite. - * @access public - */ - function &load($test_file) { - $existing_classes = get_declared_classes(); - include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); - $suite = &$this->createSuiteFromClasses($test_file, $classes); - return $suite; +/** + * Helps to extract test cases automatically from a file. + */ +class SimpleFileLoader { + + /** + * Builds a test suite from a library of test cases. + * The new suite is composed into this one. + * @param string $test_file File name of library with + * test case classes. + * @return TestSuite The new test suite. + * @access public + */ + function &load($test_file) { + $existing_classes = get_declared_classes(); + include_once($test_file); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; } - /** - * Calculates the incoming test cases. Skips abstract - * and ignored classes. - * @param array $candidates Candidate classes. - * @return array New classes which are test - * cases that shouldn't be ignored. - * @access public - */ - function selectRunnableTests($candidates) { - $classes = array(); - foreach ($candidates as $class) { - if (TestSuite::getBaseTestCase($class)) { - $reflection = new SimpleReflection($class); - if ($reflection->isAbstract()) { - SimpleTest::ignore($class); - } else { - $classes[] = $class; - } + $classes = $this->selectRunnableTests($file_classes); + $suite = &$this->createSuiteFromClasses($test_file, $classes); + return $suite; + } + + /** + * Calculates the incoming test cases. Skips abstract + * and ignored classes. + * @param array $candidates Candidate classes. + * @return array New classes which are test + * cases that shouldn't be ignored. + * @access public + */ + function selectRunnableTests($candidates) { + $classes = array(); + foreach ($candidates as $class) { + if (TestSuite::getBaseTestCase($class)) { + $reflection = new SimpleReflection($class); + if ($reflection->isAbstract()) { + SimpleTest::ignore($class); + } else { + $classes[] = $class; } } - return $classes; } + return $classes; + } - /** - * Builds a test suite from a class list. - * @param string $title Title of new group. - * @param array $classes Test classes. - * @return TestSuite Group loaded with the new - * test cases. - * @access public - */ - function &createSuiteFromClasses($title, $classes) { - if (count($classes) == 0) { - $suite = &new BadTestSuite($title, "No runnable test cases in [$title]"); - return $suite; - } - SimpleTest::ignoreParentsIfIgnored($classes); - $suite = &new TestSuite($title); - foreach ($classes as $class) { - if (! SimpleTest::isIgnored($class)) { - $suite->addTestClass($class); - } - } + /** + * Builds a test suite from a class list. + * @param string $title Title of new group. + * @param array $classes Test classes. + * @return TestSuite Group loaded with the new + * test cases. + * @access public + */ + function &createSuiteFromClasses($title, $classes) { + if (count($classes) == 0) { + $suite = &new BadTestSuite($title, "No runnable test cases in [$title]"); return $suite; } + SimpleTest::ignoreParentsIfIgnored($classes); + $suite = &new TestSuite($title); + foreach ($classes as $class) { + if (! SimpleTest::isIgnored($class)) { + $suite->addTestClass($class); + } + } + return $suite; } +} +/** + * This is a composite test class for combining + * test cases and other RunnableTest classes into + * a group test. + * @package SimpleTest + * @subpackage UnitTester + */ +class TestSuite { + var $_label; + var $_test_cases; + /** - * This is a composite test class for combining - * test cases and other RunnableTest classes into - * a group test. - * @package SimpleTest - * @subpackage UnitTester + * Sets the name of the test suite. + * @param string $label Name sent at the start and end + * of the test. + * @access public */ - class TestSuite { - var $_label; - var $_test_cases; + function TestSuite($label = false) { + $this->_label = $label; + $this->_test_cases = array(); + } - /** - * Sets the name of the test suite. - * @param string $label Name sent at the start and end - * of the test. - * @access public - */ - function TestSuite($label = false) { - $this->_label = $label; - $this->_test_cases = array(); - } + /** + * Accessor for the test name for subclasses. If the suite + * wraps a single test case the label defaults to the name of that test. + * @return string Name of the test. + * @access public + */ + function getLabel() { + if (! $this->_label) { + return ($this->getSize() == 1) ? + get_class($this->_test_cases[0]) : get_class($this); + } else { + return $this->_label; + } + } - /** - * Accessor for the test name for subclasses. If the suite - * wraps a single test case the label defaults to the name of that test. - * @return string Name of the test. - * @access public - */ - function getLabel() { - if (! $this->_label) { - return ($this->getSize() == 1) ? - get_class($this->_test_cases[0]) : get_class($this); - } else { - return $this->_label; - } + /** + * @deprecated + */ + function addTestCase(&$test_case) { + $this->_test_cases[] = &$test_case; + } + + /** + * @deprecated + */ + function addTestClass($class) { + if (TestSuite::getBaseTestCase($class) == 'testsuite') { + $this->_test_cases[] = &new $class(); + } else { + $this->_test_cases[] = $class; } + } - /** - * @deprecated - */ - function addTestCase(&$test_case) { + /** + * Adds a test into the suite by instance or class. The class will + * be instantiated if it's a test suite. + * @param SimpleTestCase $test_case Suite or individual test + * case implementing the + * runnable test interface. + * @access public + */ + function add(&$test_case) { + if (! is_string($test_case)) { $this->_test_cases[] = &$test_case; + } elseif (TestSuite::getBaseTestCase($class) == 'testsuite') { + $this->_test_cases[] = &new $class(); + } else { + $this->_test_cases[] = $class; } + } - /** - * @deprecated - */ - function addTestClass($class) { - if (TestSuite::getBaseTestCase($class) == 'testsuite') { - $this->_test_cases[] = &new $class(); + /** + * @deprecated + */ + function addTestFile($test_file) { + $this->addFile($test_file); + } + + /** + * Builds a test suite from a library of test cases. + * The new suite is composed into this one. + * @param string $test_file File name of library with + * test case classes. + * @access public + */ + function addFile($test_file) { + $extractor = new SimpleFileLoader(); + $this->add($extractor->load($test_file)); + } + + /** + * Delegates to a visiting collector to add test + * files. + * @param string $path Path to scan from. + * @param SimpleCollector $collector Directory scanner. + * @access public + */ + function collect($path, &$collector) { + $collector->collect($this, $path); + } + + /** + * Invokes run() on all of the held test cases, instantiating + * them if necessary. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run(&$reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) { + if (is_string($this->_test_cases[$i])) { + $class = $this->_test_cases[$i]; + $test = &new $class(); + $test->run($reporter); + unset($test); } else { - $this->_test_cases[] = $class; + $this->_test_cases[$i]->run($reporter); } } + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); + } - /** - * Adds a test into the suite by instance or class. The class will - * be instantiated if it's a test suite. - * @param SimpleTestCase $test_case Suite or individual test - * case implementing the - * runnable test interface. - * @access public - */ - function add(&$test_case) { - if (! is_string($test_case)) { - $this->_test_cases[] = &$test_case; - } elseif (TestSuite::getBaseTestCase($class) == 'testsuite') { - $this->_test_cases[] = &new $class(); + /** + * Number of contained test cases. + * @return integer Total count of cases in the group. + * @access public + */ + function getSize() { + $count = 0; + foreach ($this->_test_cases as $case) { + if (is_string($case)) { + $count++; } else { - $this->_test_cases[] = $class; + $count += $case->getSize(); } } + return $count; + } - /** - * @deprecated - */ - function addTestFile($test_file) { - $this->addFile($test_file); + /** + * Test to see if a class is derived from the + * SimpleTestCase class. + * @param string $class Class name. + * @access public + * @static + */ + function getBaseTestCase($class) { + while ($class = get_parent_class($class)) { + $class = strtolower($class); + if ($class == 'simpletestcase' || $class == 'testsuite') { + return $class; + } } + return false; + } +} - /** - * Builds a test suite from a library of test cases. - * The new suite is composed into this one. - * @param string $test_file File name of library with - * test case classes. - * @access public - */ - function addFile($test_file) { - $extractor = new SimpleFileLoader(); - $this->add($extractor->load($test_file)); - } +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class GroupTest extends TestSuite { } - /** - * Delegates to a visiting collector to add test - * files. - * @param string $path Path to scan from. - * @param SimpleCollector $collector Directory scanner. - * @access public - */ - function collect($path, &$collector) { - $collector->collect($this, $path); - } +/** + * This is a failing group test for when a test suite hasn't + * loaded properly. + * @package SimpleTest + * @subpackage UnitTester + */ +class BadTestSuite { + var $_label; + var $_error; - /** - * Invokes run() on all of the held test cases, instantiating - * them if necessary. - * @param SimpleReporter $reporter Current test reporter. - * @access public - */ - function run(&$reporter) { - $reporter->paintGroupStart($this->getLabel(), $this->getSize()); - for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) { - if (is_string($this->_test_cases[$i])) { - $class = $this->_test_cases[$i]; - $test = &new $class(); - $test->run($reporter); - unset($test); - } else { - $this->_test_cases[$i]->run($reporter); - } - } - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - /** - * Number of contained test cases. - * @return integer Total count of cases in the group. - * @access public - */ - function getSize() { - $count = 0; - foreach ($this->_test_cases as $case) { - if (is_string($case)) { - $count++; - } else { - $count += $case->getSize(); - } - } - return $count; - } - - /** - * Test to see if a class is derived from the - * SimpleTestCase class. - * @param string $class Class name. - * @access public - * @static - */ - function getBaseTestCase($class) { - while ($class = get_parent_class($class)) { - $class = strtolower($class); - if ($class == 'simpletestcase' || $class == 'testsuite') { - return $class; - } - } - return false; - } + /** + * Sets the name of the test suite and error message. + * @param string $label Name sent at the start and end + * of the test. + * @access public + */ + function BadTestSuite($label, $error) { + $this->_label = $label; + $this->_error = $error; } /** - * @package SimpleTest - * @subpackage UnitTester - * @deprecated + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public */ - class GroupTest extends TestSuite { } + function getLabel() { + return $this->_label; + } /** - * This is a failing group test for when a test suite hasn't - * loaded properly. - * @package SimpleTest - * @subpackage UnitTester + * Sends a single error to the reporter. + * @param SimpleReporter $reporter Current test reporter. + * @access public */ - class BadTestSuite { - var $_label; - var $_error; - - /** - * Sets the name of the test suite and error message. - * @param string $label Name sent at the start and end - * of the test. - * @access public - */ - function BadTestSuite($label, $error) { - $this->_label = $label; - $this->_error = $error; - } - - /** - * Accessor for the test name for subclasses. - * @return string Name of the test. - * @access public - */ - function getLabel() { - return $this->_label; - } - - /** - * Sends a single error to the reporter. - * @param SimpleReporter $reporter Current test reporter. - * @access public - */ - function run(&$reporter) { - $reporter->paintGroupStart($this->getLabel(), $this->getSize()); - $reporter->paintFail('Bad TestSuite [' . $this->getLabel() . - '] with error [' . $this->_error . ']'); - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - /** - * Number of contained test cases. Always zero. - * @return integer Total count of cases in the group. - * @access public - */ - function getSize() { - return 0; - } + function run(&$reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + $reporter->paintFail('Bad TestSuite [' . $this->getLabel() . + '] with error [' . $this->_error . ']'); + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); } /** - * @package SimpleTest - * @subpackage UnitTester - * @deprecated + * Number of contained test cases. Always zero. + * @return integer Total count of cases in the group. + * @access public */ - class BadGroupTest extends BadTestSuite { } + function getSize() { + return 0; + } +} + +/** + * @package SimpleTest + * @subpackage UnitTester + * @deprecated + */ +class BadGroupTest extends BadTestSuite { } ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pp11@us...> - 2008-02-26 20:41:30
|
Revision: 1660 http://simpletest.svn.sourceforge.net/simpletest/?rev=1660&view=rev Author: pp11 Date: 2008-02-26 12:41:25 -0800 (Tue, 26 Feb 2008) Log Message: ----------- New tests for UTF8 inside the browser. Be careful (utf8_test.php) is using UTF8 ! Modified Paths: -------------- simpletest/trunk/TODO.xml Added Paths: ----------- simpletest/trunk/test/utf8_test.php Modified: simpletest/trunk/TODO.xml =================================================================== --- simpletest/trunk/TODO.xml 2008-02-18 12:42:54 UTC (rev 1659) +++ simpletest/trunk/TODO.xml 2008-02-26 20:41:25 UTC (rev 1660) @@ -53,7 +53,7 @@ <dt class="done"> Fix bug 1671539 with assertText picking up JavaScript (1). </dt> - <dt> + <dt class="done"> Add U flag to regexes to allow unicode (3). </dt> </dl> @@ -113,6 +113,7 @@ It means going through all of the core documentation and updating it with new methods and features. In particular, the introductory pages should switch to autoload. + Should be checked : addTestFile. </dd> <dt class="done"> Extension docs (1). Added: simpletest/trunk/test/utf8_test.php =================================================================== --- simpletest/trunk/test/utf8_test.php (rev 0) +++ simpletest/trunk/test/utf8_test.php 2008-02-26 20:41:25 UTC (rev 1660) @@ -0,0 +1,78 @@ +<?php +// $Id: parser_test.php 1608 2007-12-27 09:03:07Z pp11 $ +// Handle with care : this file is UTF8. + +require_once(dirname(__FILE__) . '/../autorun.php'); +require_once(dirname(__FILE__) . '/../parser.php'); +require_once(dirname(__FILE__) . '/../url.php'); +Mock::generate('SimpleHtmlSaxParser'); +Mock::generate('SimpleSaxListener'); + +class TestOfHtmlSaxParserWithDifferentCharset extends UnitTestCase { + function testWithTextInUTF8() { + $regex = &new ParallelRegex(false); + $regex->addPattern("eé"); + $this->assertTrue($regex->match("eéêè", $match)); + $this->assertEqual($match, "eé"); + } + + function testWithTextInLatin1() { + $regex = &new ParallelRegex(false); + $regex->addPattern(utf8_decode("eé")); + $this->assertTrue($regex->match(utf8_decode("eéêè"), $match)); + $this->assertEqual($match, utf8_decode("eé")); + } + + function &createParser() { + $parser = &new MockSimpleHtmlSaxParser(); + $parser->setReturnValue('acceptStartToken', true); + $parser->setReturnValue('acceptEndToken', true); + $parser->setReturnValue('acceptAttributeToken', true); + $parser->setReturnValue('acceptEntityToken', true); + $parser->setReturnValue('acceptTextToken', true); + $parser->setReturnValue('ignore', true); + return $parser; + } + + function testTagWithAttributesInUTF8() { + $parser = &$this->createParser(); + $parser->expectOnce('acceptTextToken', array('label', '*')); + $parser->expectAt(0, 'acceptStartToken', array('<a', '*')); + $parser->expectAt(1, 'acceptStartToken', array('href', '*')); + $parser->expectAt(2, 'acceptStartToken', array('>', '*')); + $parser->expectCallCount('acceptStartToken', 3); + $parser->expectAt(0, 'acceptAttributeToken', array('= "', '*')); + $parser->expectAt(1, 'acceptAttributeToken', array('hère.html', '*')); + $parser->expectAt(2, 'acceptAttributeToken', array('"', '*')); + $parser->expectCallCount('acceptAttributeToken', 3); + $parser->expectOnce('acceptEndToken', array('</a>', '*')); + $lexer = &new SimpleHtmlLexer($parser); + $this->assertTrue($lexer->parse('<a href = "hère.html">label</a>')); + } + + function testTagWithAttributesInLatin1() { + $parser = &$this->createParser(); + $parser->expectOnce('acceptTextToken', array('label', '*')); + $parser->expectAt(0, 'acceptStartToken', array('<a', '*')); + $parser->expectAt(1, 'acceptStartToken', array('href', '*')); + $parser->expectAt(2, 'acceptStartToken', array('>', '*')); + $parser->expectCallCount('acceptStartToken', 3); + $parser->expectAt(0, 'acceptAttributeToken', array('= "', '*')); + $parser->expectAt(1, 'acceptAttributeToken', array(utf8_decode('hère.html'), '*')); + $parser->expectAt(2, 'acceptAttributeToken', array('"', '*')); + $parser->expectCallCount('acceptAttributeToken', 3); + $parser->expectOnce('acceptEndToken', array('</a>', '*')); + $lexer = &new SimpleHtmlLexer($parser); + $this->assertTrue($lexer->parse(utf8_decode('<a href = "hère.html">label</a>'))); + } +} + +class TestOfUrlithDifferentCharset extends UnitTestCase { + function testUsernameAndPasswordInUTF8() { + $url = new SimpleUrl('http://pÈrick:penËt@...';); + $this->assertEqual($url->getUsername(), 'pÈrick'); + $this->assertEqual($url->getPassword(), 'penËt'); + } +} + +?> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: SourceForge.net <noreply@so...> - 2008-02-26 14:30:19
|
Patches item #1902180, was opened at 2008-02-26 15:29 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: autorun.php: configure Reporter to use Initial Comment: The attached patch allows configuration of the Reporter to use in autorun.php: If the global $AUTORUN_REPORTER is set, it's used instead of the DefaultReporter. This is useful when using autorun.php, which is really convenient, but you want to use e.g. an own ShowPassesReporter. ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-26 15:30 Message: Logged In: YES user_id=663176 Originator: YES File Added: simpletest-autorun-configure-reporter-plus-whitespace.diff ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-26 14:29:12
|
Patches item #1902180, was opened at 2008-02-26 15:29 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: autorun.php: configure Reporter to use Initial Comment: The attached patch allows configuration of the Reporter to use in autorun.php: If the global $AUTORUN_REPORTER is set, it's used instead of the DefaultReporter. This is useful when using autorun.php, which is really convenient, but you want to use e.g. an own ShowPassesReporter. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1902180&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-25 11:51:16
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-25 12:51 Message: Logged In: YES user_id=663176 Originator: YES It actually works also from the browser.. The problem has been that the "support/test1.php" file wasn't copied to the system where I've tested it with the browser.. and the "require_once"-error has been suppressed. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 09:03 Message: Logged In: YES user_id=663176 Originator: YES Well, the test only works if called with "php -f" from the command line, but not from the browser, where it says: test_load_if_included.php Fail: -> Bad TestSuite [test_load_if_included.php] with error [No runnable test cases in [test_load_if_included.php]] 0/0 test cases complete: 0 passes, 1 fails and 0 exceptions. I think you can figure this out better than me and integrate it properly in the existing tests. Thank you. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-25 08:03:16
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-25 09:03 Message: Logged In: YES user_id=663176 Originator: YES Well, the test only works if called with "php -f" from the command line, but not from the browser, where it says: test_load_if_included.php Fail: -> Bad TestSuite [test_load_if_included.php] with error [No runnable test cases in [test_load_if_included.php]] 0/0 test cases complete: 0 passes, 1 fails and 0 exceptions. I think you can figure this out better than me and integrate it properly in the existing tests. Thank you. ---------------------------------------------------------------------- Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-25 07:50:44
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by blueyed You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: daniel hahler (blueyed) Date: 2008-02-25 08:50 Message: Logged In: YES user_id=663176 Originator: YES File Added: test_load_if_included.php ---------------------------------------------------------------------- Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-23 10:56:01
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Comment added) made by pp11 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- >Comment By: Perrick Penet (pp11) Date: 2008-02-23 11:55 Message: Logged In: YES user_id=292377 Originator: NO Hi Daniel, Thanks for the patch : do you have a failing test case as well ? It would mean having the patch accepted a lot sooner. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-22 17:43:24
|
Patches item #1899780, was opened at 2008-02-22 18:43 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: daniel hahler (blueyed) Assigned to: Nobody/Anonymous (nobody) Summary: SimpleFileLoader::load: fix for $test_file already included Initial Comment: When the $test_file has already been included, before SimpleFileLoader::load($test_file) gets called, the include_once will be skipped and no new classes show up for get_declared_classes(). The attached patch will use a regular expression to find classes in $test_file, in case $file_classes is empty. --- test_case.php (Revision 1659) +++ test_case.php (Arbeitskopie) @@ -388,8 +388,15 @@ function &load($test_file) { $existing_classes = get_declared_classes(); include_once($test_file); - $classes = $this->selectRunnableTests( - array_diff(get_declared_classes(), $existing_classes)); + $file_classes = array_diff(get_declared_classes(), $existing_classes); + + // Lookup classnames from file contents, in case the file may have been included before: + if( empty($file_classes) ) { + preg_match_all( '~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', file_get_contents($test_file), $matches ); + $file_classes = $matches[1]; + } + + $classes = $this->selectRunnableTests($file_classes); $suite = &$this->createSuiteFromClasses($test_file, $classes); return $suite; } ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1899780&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-19 05:59:59
|
Feature Requests item #1896659, was opened at 2008-02-19 05:41 Message generated for change (Comment added) made by d11wtq You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: d11wtq (Chris Corbyn) (d11wtq) Assigned to: Nobody/Anonymous (nobody) Summary: Allow Mocks to be generated in namespaces Initial Comment: Practical experience with PHP5.3 and namespaces is proving to be a little painful in combination with simpletest. More specifically, with the generation of Mock objects. Could you perhaps: 1.) Allow Mock::generate('Bar::Foo', 'Bar::MockFoo'); 2.) Check if the namespace syntax is present in either $class or $mock_class and strip it if so. 3.) Capture that namespace in a class field of MockGenerator. 4.) Place the namespace declaration (if any) at the top of the eval()'d code. This would make writing tests under PHP5.3 much easier. Obviously it's still in development, but I can't see this being backward incompatible if implemented now since you can't use :: syntax in 5.2 so nobody should be passing those names as arguments to Mock::generate(). ----------------- $code = ""; if (!is_null($this->_namespace)) { $code .= "namespace " . $this->_namespace . ";\n"; } $code .= "class " . $this->_mock_class . "{\n"; .. and so on ... ---------------- :) ---------------------------------------------------------------------- >Comment By: d11wtq (Chris Corbyn) (d11wtq) Date: 2008-02-19 05:59 Message: Logged In: YES user_id=1355972 Originator: YES File Added: patch.diff ---------------------------------------------------------------------- Comment By: d11wtq (Chris Corbyn) (d11wtq) Date: 2008-02-19 05:51 Message: Logged In: YES user_id=1355972 Originator: YES This will probably be buggy.. but it took me like 5 minutes and it seems to work in my scenario. I dare say there needs to be some checking for the value of the __NAMESPACE__ constant in some cases, although from what I can tell the eval()'d code will always be distinctly separate from the namespace it is produced under. File Added: patch.diff ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-19 05:52:05
|
Feature Requests item #1896659, was opened at 2008-02-19 05:41 Message generated for change (Comment added) made by d11wtq You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: d11wtq (Chris Corbyn) (d11wtq) Assigned to: Nobody/Anonymous (nobody) Summary: Allow Mocks to be generated in namespaces Initial Comment: Practical experience with PHP5.3 and namespaces is proving to be a little painful in combination with simpletest. More specifically, with the generation of Mock objects. Could you perhaps: 1.) Allow Mock::generate('Bar::Foo', 'Bar::MockFoo'); 2.) Check if the namespace syntax is present in either $class or $mock_class and strip it if so. 3.) Capture that namespace in a class field of MockGenerator. 4.) Place the namespace declaration (if any) at the top of the eval()'d code. This would make writing tests under PHP5.3 much easier. Obviously it's still in development, but I can't see this being backward incompatible if implemented now since you can't use :: syntax in 5.2 so nobody should be passing those names as arguments to Mock::generate(). ----------------- $code = ""; if (!is_null($this->_namespace)) { $code .= "namespace " . $this->_namespace . ";\n"; } $code .= "class " . $this->_mock_class . "{\n"; .. and so on ... ---------------- :) ---------------------------------------------------------------------- >Comment By: d11wtq (Chris Corbyn) (d11wtq) Date: 2008-02-19 05:51 Message: Logged In: YES user_id=1355972 Originator: YES This will probably be buggy.. but it took me like 5 minutes and it seems to work in my scenario. I dare say there needs to be some checking for the value of the __NAMESPACE__ constant in some cases, although from what I can tell the eval()'d code will always be distinctly separate from the namespace it is produced under. File Added: patch.diff ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 |
From: SourceForge.net <noreply@so...> - 2008-02-19 05:41:30
|
Feature Requests item #1896659, was opened at 2008-02-19 05:41 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Priority: 5 Private: No Submitted By: d11wtq (Chris Corbyn) (d11wtq) Assigned to: Nobody/Anonymous (nobody) Summary: Allow Mocks to be generated in namespaces Initial Comment: Practical experience with PHP5.3 and namespaces is proving to be a little painful in combination with simpletest. More specifically, with the generation of Mock objects. Could you perhaps: 1.) Allow Mock::generate('Bar::Foo', 'Bar::MockFoo'); 2.) Check if the namespace syntax is present in either $class or $mock_class and strip it if so. 3.) Capture that namespace in a class field of MockGenerator. 4.) Place the namespace declaration (if any) at the top of the eval()'d code. This would make writing tests under PHP5.3 much easier. Obviously it's still in development, but I can't see this being backward incompatible if implemented now since you can't use :: syntax in 5.2 so nobody should be passing those names as arguments to Mock::generate(). ----------------- $code = ""; if (!is_null($this->_namespace)) { $code .= "namespace " . $this->_namespace . ";\n"; } $code .= "class " . $this->_mock_class . "{\n"; .. and so on ... ---------------- :) ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547458&aid=1896659&group_id=76550 |
From: <pp11@us...> - 2008-02-18 12:43:00
|
Revision: 1659 http://simpletest.svn.sourceforge.net/simpletest/?rev=1659&view=rev Author: pp11 Date: 2008-02-18 04:42:54 -0800 (Mon, 18 Feb 2008) Log Message: ----------- All source files now use <introduction /> and <section /> Modified Paths: -------------- simpletest/trunk/docs/source/en/intro.xml simpletest/trunk/docs/source/fr/boundary_classes_tutorial.xml simpletest/trunk/docs/source/fr/display_subclass_tutorial.xml simpletest/trunk/docs/source/fr/first_test_tutorial.xml simpletest/trunk/docs/source/fr/gain_control_tutorial.xml simpletest/trunk/docs/source/fr/group_test_tutorial.xml simpletest/trunk/docs/source/fr/improving_design_tutorial.xml simpletest/trunk/docs/source/fr/intro.xml simpletest/trunk/docs/source/fr/mock_objects_tutorial.xml simpletest/trunk/docs/source/fr/subclass_tutorial.xml simpletest/trunk/docs/source/fr/support_website.xml simpletest/trunk/packages/simpletest.org/index.php Modified: simpletest/trunk/docs/source/en/intro.xml =================================================================== --- simpletest/trunk/docs/source/en/intro.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/en/intro.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -5,29 +5,31 @@ and Object Oriented development </long_title> <content> - <p> - The <a local="simple_test">SimpleTest PHP unit tester</a> is in - the 1.0.1 release cycle and is available for download from your nearest <a - href="http://souceforge.net/projects/simpletest/">SourceForge</a>. - </p> - <p> - It is a PHP unit test, mock objects and web test framework. - Users of <a href="http://www.junit.org/">JUnit</a> will be - familiar with most of the interface. - <a href="http://jwebunit.sourceforge.net/">JWebUnit</a> - style functionality is more complete now. - It has support for SSL, frames, proxies, basic authentication and the - standard HTML controls. - The idea is that common but fiddly PHP tasks, such as logging into a site, - can be tested easily. - </p> - <p> - There is currently no support for JavaScript in the web tester. - For testing these elements we recommend - <a href="http://www.edwardh.com/jsunit/">JSUnit</a> - or - <a href="http://selenium.thoughtworks.com/index.html">Selenium</a>. - </p> + <introduction> + <p> + The <a local="simple_test">SimpleTest PHP unit tester</a> is in + the 1.0.1 release cycle and is available for download from your nearest <a + href="http://souceforge.net/projects/simpletest/">SourceForge</a>. + </p> + <p> + It is a PHP unit test, mock objects and web test framework. + Users of <a href="http://www.junit.org/">JUnit</a> will be + familiar with most of the interface. + <a href="http://jwebunit.sourceforge.net/">JWebUnit</a> + style functionality is more complete now. + It has support for SSL, frames, proxies, basic authentication and the + standard HTML controls. + The idea is that common but fiddly PHP tasks, such as logging into a site, + can be tested easily. + </p> + <p> + There is currently no support for JavaScript in the web tester. + For testing these elements we recommend + <a href="http://www.edwardh.com/jsunit/">JSUnit</a> + or + <a href="http://selenium.thoughtworks.com/index.html">Selenium</a>. + </p> + </introduction> </content> <meta> <keywords> Modified: simpletest/trunk/docs/source/fr/boundary_classes_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/fr/boundary_classes_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/fr/boundary_classes_tutorial.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -4,32 +4,43 @@ Tutorial de tests unitaires PHP - Organiser les tests unitaires et les sc\xE9narios de test de classe fronti\xE8re </long_title> <content> - <p> - Vous pensez probablement que nous avons d\xE9sormais \xE9puis\xE9 les modifications sur la classe <code>Log</code> et qu'il n'y a plus rien \xE0 ajouter. Sauf que les choses ne sont jamais simples avec la Programmation Orient\xE9 Objet. Vous pensez comprendre un probl\xE8me et un nouveau cas arrive : il d\xE9fie votre point de vue et vous conduit vers une analyse encore plus profonde. Je pensais comprendre la classe de log et que seule la premi\xE8re page du tutorial l'utiliserait. Apr\xE8s \xE7a, je serais pass\xE9 \xE0 quelque chose de plus compliqu\xE9. Personne n'est plus surpris que moi de ne pas l'avoir boucl\xE9e. En fait je pense que je viens \xE0 peine de me rendre compte de ce qu'un loggueur fait. - </p> - <p> - <a class="target" name="variation"><h2>Variations sur un log</h2></a> - </p> - <p> - Supposons que nous ne voulons plus seulement enregistrer les logs vers un fichier. Nous pourrions vouloir les afficher \xE0 l'\xE9cran, les envoyer au daemon <em>syslog</em> d'Unix(tm) via un socket. Comment s'accommoder de tels changements ? - </p> - <p> - Le plus simple est de cr\xE9er des sous-classes de <code>Log</code> qui \xE9crasent la m\xE9thode <code>message()</code> avec les nouvelles versions. Ce syst\xE8me fonctionne bien \xE0 court terme, sauf qu'il a quelque chose de subtilement mais fonci\xE8rement erron\xE9. Supposons que nous cr\xE9ions ces sous-classes et que nous ayons des loggueurs \xE9crivant vers un fichier, sur l'\xE9cran et via le r\xE9seau. Trois classes en tout : \xE7a fonctionne. Maintenant supposons que nous voulons ajouter une nouvelle classe de log qui ajoute un filtrage par priorit\xE9 des messages, ne laissant passer que les messages d'un certain type, le tout suivant un fichier de configuration. - </p> - <p> - Nous sommes coinc\xE9s. Si nous cr\xE9ons de nouvelles sous-classes, nous devons le faire pour l'ensemble des trois classes, ce qui nous donnerait six classes. L'envergure de la duplication est horrible. - </p> - <p> - Alors, est-ce que vous \xEAtes en train de souhaiter que PHP ait l'h\xE9ritage multiple ? Effectivement, cela r\xE9duirait l'ampleur de la t\xE2che \xE0 court terme, mais aussi compliquerait quelque chose qui devrait \xEAtre une classe tr\xE8s simple. L'h\xE9ritage multiple, m\xEAme support\xE9, devrait \xEAtre utilis\xE9 avec le plus grand soin car toutes sortes d'enchev\xEAtrements peuvent en d\xE9couler. En fait ce soudain besoin nous dit quelque chose d'autre - peut-\xEAtre que notre erreur si situe au niveau de la conception. - </p> - <p> - Qu'est-ce que doit faire un loggueur ? Est-ce qu'il envoie un message vers un fichier ? A l'\xE9cran ? Via le r\xE9seau ? Non. Il envoie un message, point final. La cible de ses messages peut \xEAtre s\xE9lectionn\xE9e \xE0 l'initialisation du log, mais apr\xE8s \xE7a pas touche : le loggueur doit pouvoir combiner et formater les \xE9l\xE9ments du message puisque tel est son v\xE9ritable boulot. Pr\xE9sumer que la cible fut un nom de fichier \xE9tait une belle paire d'oeill\xE8res. - </p> - <p> - <a class="target" name="scripteur"><h2>Abstraire un fichier vers un scripteur</h2></a> - </p> - <p> - La solution de cette mauvaise passe est un classique. Tout d'abord nous encapsulons la variation de la classe : cela ajoute un niveau d'indirection. Au lieu d'introduire le nom du fichier comme une cha\xEEne, nous l'introduisons comme "cette chose vers laquelle on \xE9crit" et que nous appelons un <code>Writer</code>. Retour aux tests... + <introduction> + <p> + Vous pensez probablement que nous avons d\xE9sormais \xE9puis\xE9 + les modifications sur la classe <code>Log</code> + et qu'il n'y a plus rien \xE0 ajouter. + Sauf que les choses ne sont jamais simples avec la Programmation Orient\xE9 Objet. + Vous pensez comprendre un probl\xE8me et un nouveau cas arrive : + il d\xE9fie votre point de vue et vous conduit + vers une analyse encore plus profonde. + Je pensais comprendre la classe de log et + que seule la premi\xE8re page du tutorial l'utiliserait. + Apr\xE8s \xE7a, je serais pass\xE9 \xE0 quelque chose de plus compliqu\xE9. + Personne n'est plus surpris que moi de ne pas l'avoir boucl\xE9e. + En fait je pense que je viens \xE0 peine + de me rendre compte de ce qu'un loggueur fait. + </p> + </introduction> + <section name="variation" title="Variations sur un log"> + <p> + Supposons que nous ne voulons plus seulement enregistrer les logs vers un fichier. Nous pourrions vouloir les afficher \xE0 l'\xE9cran, les envoyer au daemon <em>syslog</em> d'Unix(tm) via un socket. Comment s'accommoder de tels changements ? + </p> + <p> + Le plus simple est de cr\xE9er des sous-classes de <code>Log</code> qui \xE9crasent la m\xE9thode <code>message()</code> avec les nouvelles versions. Ce syst\xE8me fonctionne bien \xE0 court terme, sauf qu'il a quelque chose de subtilement mais fonci\xE8rement erron\xE9. Supposons que nous cr\xE9ions ces sous-classes et que nous ayons des loggueurs \xE9crivant vers un fichier, sur l'\xE9cran et via le r\xE9seau. Trois classes en tout : \xE7a fonctionne. Maintenant supposons que nous voulons ajouter une nouvelle classe de log qui ajoute un filtrage par priorit\xE9 des messages, ne laissant passer que les messages d'un certain type, le tout suivant un fichier de configuration. + </p> + <p> + Nous sommes coinc\xE9s. Si nous cr\xE9ons de nouvelles sous-classes, nous devons le faire pour l'ensemble des trois classes, ce qui nous donnerait six classes. L'envergure de la duplication est horrible. + </p> + <p> + Alors, est-ce que vous \xEAtes en train de souhaiter que PHP ait l'h\xE9ritage multiple ? Effectivement, cela r\xE9duirait l'ampleur de la t\xE2che \xE0 court terme, mais aussi compliquerait quelque chose qui devrait \xEAtre une classe tr\xE8s simple. L'h\xE9ritage multiple, m\xEAme support\xE9, devrait \xEAtre utilis\xE9 avec le plus grand soin car toutes sortes d'enchev\xEAtrements peuvent en d\xE9couler. En fait ce soudain besoin nous dit quelque chose d'autre - peut-\xEAtre que notre erreur si situe au niveau de la conception. + </p> + <p> + Qu'est-ce que doit faire un loggueur ? Est-ce qu'il envoie un message vers un fichier ? A l'\xE9cran ? Via le r\xE9seau ? Non. Il envoie un message, point final. La cible de ses messages peut \xEAtre s\xE9lectionn\xE9e \xE0 l'initialisation du log, mais apr\xE8s \xE7a pas touche : le loggueur doit pouvoir combiner et formater les \xE9l\xE9ments du message puisque tel est son v\xE9ritable boulot. Pr\xE9sumer que la cible fut un nom de fichier \xE9tait une belle paire d'oeill\xE8res. + </p> + </section> + <section name="scripteur" title="Abstraire un fichier vers un scripteur"> + <p> + La solution de cette mauvaise passe est un classique. Tout d'abord nous encapsulons la variation de la classe : cela ajoute un niveau d'indirection. Au lieu d'introduire le nom du fichier comme une cha\xEEne, nous l'introduisons comme "cette chose vers laquelle on \xE9crit" et que nous appelons un <code>Writer</code>. Retour aux tests... <php><![CDATA[ <?php require_once('../classes/log.php'); @@ -81,10 +92,10 @@ } ?> ]]></php> - Je vais parcourir ces tests pas \xE0 pas pour ne pas ajouter trop de confusion. J'ai remplac\xE9 les noms de fichier par une classe imaginaire <code>FileWriter</code> en provenance d'un fichier <em>classes/writer.php</em>. Par cons\xE9quent les tests devraient planter puisque nous n'avons pas encore \xE9crit ce scripteur. Doit-on le faire maintenant ? - </p> - <p> - Nous pourrions, mais ce n'est pas oblig\xE9. Par contre nous avons besoin de cr\xE9er l'interface, ou alors il ne sera pas possible de la simuler. Au final <em>classes/writer.php</em> ressemble \xE0... + Je vais parcourir ces tests pas \xE0 pas pour ne pas ajouter trop de confusion. J'ai remplac\xE9 les noms de fichier par une classe imaginaire <code>FileWriter</code> en provenance d'un fichier <em>classes/writer.php</em>. Par cons\xE9quent les tests devraient planter puisque nous n'avons pas encore \xE9crit ce scripteur. Doit-on le faire maintenant ? + </p> + <p> + Nous pourrions, mais ce n'est pas oblig\xE9. Par contre nous avons besoin de cr\xE9er l'interface, ou alors il ne sera pas possible de la simuler. Au final <em>classes/writer.php</em> ressemble \xE0... <php><![CDATA[ <?php class FileWriter { @@ -97,7 +108,7 @@ } ?> ]]></php> - Nous avons aussi besoin de modifier la classe <code>Log</code>... + Nous avons aussi besoin de modifier la classe <code>Log</code>... <php><![CDATA[ <?php require_once('../classes/clock.php');<strong> @@ -119,16 +130,16 @@ } ?> ]]></php> - Il n'y a pas grand chose qui n'ait pas chang\xE9 y compris dans la plus petite de nos classes. D\xE9sormais les tests s'ex\xE9cutent mais ne passent pas, \xE0 moins que nous ajoutions du code dans le scripteur. Alors que faisons nous ? - </p> - <p> - Nous pourrions commencer par \xE9crire des tests et d\xE9velopper la classe <code>FileWriter</code> parall\xE8lement, mais lors de cette \xE9tape nos tests de <code>Log</code> continueraient d'\xE9chouer et de nous distraire. En fait nous n'en avons pas besoin. - </p> - <p> - Une partie de notre objectif est de lib\xE9rer la classe du loggueur de l'emprise du syst\xE8me de fichiers et il existe un moyen d'y arriver. Tout d'abord nous cr\xE9ons le fichier <em>tests/writer_test.php</em> de mani\xE8re \xE0 avoir un endroit pour placer notre code test en provenance de <em>log_test.php</em> et que nous allons brasser. Sauf que je ne vais pas l'ajouter dans le fichier <em>all_tests.php</em> pour l'instant puisque qu'il s'agit de la partie de log que nous sommes en train d'aborder. - </p> - <p> - Nous enlevons tous les test de <em>log_test.php</em> qui ne sont pas strictement en lien avec le journal et nous les gardons bien pr\xE9cieusement dans <em>writer_test.php</em> pour plus tard. Nous allons aussi simuler le scripteur pour qu'il n'\xE9crive pas r\xE9ellement dans un fichier... + Il n'y a pas grand chose qui n'ait pas chang\xE9 y compris dans la plus petite de nos classes. D\xE9sormais les tests s'ex\xE9cutent mais ne passent pas, \xE0 moins que nous ajoutions du code dans le scripteur. Alors que faisons nous ? + </p> + <p> + Nous pourrions commencer par \xE9crire des tests et d\xE9velopper la classe <code>FileWriter</code> parall\xE8lement, mais lors de cette \xE9tape nos tests de <code>Log</code> continueraient d'\xE9chouer et de nous distraire. En fait nous n'en avons pas besoin. + </p> + <p> + Une partie de notre objectif est de lib\xE9rer la classe du loggueur de l'emprise du syst\xE8me de fichiers et il existe un moyen d'y arriver. Tout d'abord nous cr\xE9ons le fichier <em>tests/writer_test.php</em> de mani\xE8re \xE0 avoir un endroit pour placer notre code test en provenance de <em>log_test.php</em> et que nous allons brasser. Sauf que je ne vais pas l'ajouter dans le fichier <em>all_tests.php</em> pour l'instant puisque qu'il s'agit de la partie de log que nous sommes en train d'aborder. + </p> + <p> + Nous enlevons tous les test de <em>log_test.php</em> qui ne sont pas strictement en lien avec le journal et nous les gardons bien pr\xE9cieusement dans <em>writer_test.php</em> pour plus tard. Nous allons aussi simuler le scripteur pour qu'il n'\xE9crive pas r\xE9ellement dans un fichier... <php><![CDATA[ <?php require_once('../classes/log.php'); @@ -154,38 +165,38 @@ } ?> ]]></php> - Eh oui c'est tout : il s'agit bien de l'ensemble du sc\xE9nario de test et c'est normal qu'il soit aussi court. Pas mal de choses se sont pass\xE9es... - <ol> - <li> - La n\xE9cessit\xE9 de cr\xE9er le fichier uniquement si n\xE9cessaire a \xE9t\xE9 d\xE9plac\xE9e vers le <code>FileWriter</code>. - </li> - <li> - \xC9tant donn\xE9 que nous travaillons avec des objets fantaisie, aucun fichier n'a \xE9t\xE9 cr\xE9\xE9 et donc <code>setUp()</code> et <code>tearDown()</code> passent dans les tests du scripteur. - </li> - <li> - D\xE9sormais le test consiste simplement dans l'envoi d'un message type et du test de son format. - </li> - </ol> - Attendez un instant, o\xF9 sont les assertions ? - </p> - <p> - Les objets fantaisie font beaucoup plus que se comporter comme des objets, ils ex\xE9cutent aussi des test. L'appel <code>expectArguments()</code> dit \xE0 l'objet fantaisie d'attendre un seul param\xE8tre de la cha\xEEne "[Timestamp] Test" quand la m\xE9thode fantaise <code>write()</code> est appel\xE9e. Lorsque cette m\xE9thode est appel\xE9e les param\xE8tres attendus sont compar\xE9s avec ceci et un succ\xE8s ou un \xE9chec est renvoy\xE9 comme r\xE9sultat au test unitaire. C'est pourquoi un nouvel objet fantaisie a une r\xE9f\xE9rence vers <code>$this</code> dans son constructeur, il a besoin de ce <code>$this</code> pour l'envoi de son propre r\xE9sultat. - </p> - <p> - L'autre attente, c'est que le <code>write</code> ne soit appel\xE9 qu'une seule et unique fois. Juste l'initialiser ne serait pas suffisant. L'objet fantaisie attendrait une \xE9ternit\xE9 si la m\xE9thode n'\xE9tait jamais appel\xE9e et par cons\xE9quent n'enverrait jamais le message d'erreur \xE0 la fin du test. Pour y faire face, l'appel <code>tally()</code> lui dit de v\xE9rifier le nombre d'appel \xE0 ce moment l\xE0. Nous pouvons voir tout \xE7a en lan\xE7ant les tests... - <div class="demo"> - <h1>All tests</h1> - <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Arguments for [write] were [String: [Timestamp] Test line]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Expected call count for [write] was [1], but got [1]<br /> - - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>4</strong> passes and <strong>0</strong> fails.</div> - </div> - </p> - <p> - En fait nous pouvons encore raccourcir nos tests. L'attente de l'objet fantaisie <code>expectOnce()</code> peut combiner les deux attentes s\xE9par\xE9es. + Eh oui c'est tout : il s'agit bien de l'ensemble du sc\xE9nario de test et c'est normal qu'il soit aussi court. Pas mal de choses se sont pass\xE9es... + <ol> + <li> + La n\xE9cessit\xE9 de cr\xE9er le fichier uniquement si n\xE9cessaire a \xE9t\xE9 d\xE9plac\xE9e vers le <code>FileWriter</code>. + </li> + <li> + \xC9tant donn\xE9 que nous travaillons avec des objets fantaisie, aucun fichier n'a \xE9t\xE9 cr\xE9\xE9 et donc <code>setUp()</code> et <code>tearDown()</code> passent dans les tests du scripteur. + </li> + <li> + D\xE9sormais le test consiste simplement dans l'envoi d'un message type et du test de son format. + </li> + </ol> + Attendez un instant, o\xF9 sont les assertions ? + </p> + <p> + Les objets fantaisie font beaucoup plus que se comporter comme des objets, ils ex\xE9cutent aussi des test. L'appel <code>expectArguments()</code> dit \xE0 l'objet fantaisie d'attendre un seul param\xE8tre de la cha\xEEne "[Timestamp] Test" quand la m\xE9thode fantaise <code>write()</code> est appel\xE9e. Lorsque cette m\xE9thode est appel\xE9e les param\xE8tres attendus sont compar\xE9s avec ceci et un succ\xE8s ou un \xE9chec est renvoy\xE9 comme r\xE9sultat au test unitaire. C'est pourquoi un nouvel objet fantaisie a une r\xE9f\xE9rence vers <code>$this</code> dans son constructeur, il a besoin de ce <code>$this</code> pour l'envoi de son propre r\xE9sultat. + </p> + <p> + L'autre attente, c'est que le <code>write</code> ne soit appel\xE9 qu'une seule et unique fois. Juste l'initialiser ne serait pas suffisant. L'objet fantaisie attendrait une \xE9ternit\xE9 si la m\xE9thode n'\xE9tait jamais appel\xE9e et par cons\xE9quent n'enverrait jamais le message d'erreur \xE0 la fin du test. Pour y faire face, l'appel <code>tally()</code> lui dit de v\xE9rifier le nombre d'appel \xE0 ce moment l\xE0. Nous pouvons voir tout \xE7a en lan\xE7ant les tests... + <div class="demo"> + <h1>All tests</h1> + <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Arguments for [write] were [String: [Timestamp] Test line]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Expected call count for [write] was [1], but got [1]<br /> + + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>4</strong> passes and <strong>0</strong> fails.</div> + </div> + </p> + <p> + En fait nous pouvons encore raccourcir nos tests. L'attente de l'objet fantaisie <code>expectOnce()</code> peut combiner les deux attentes s\xE9par\xE9es. <php><![CDATA[ function testWriting() { $clock = &new MockClock($this); @@ -197,29 +208,29 @@ $writer->tally(); } ]]></php> - Cela peut \xEAtre une abr\xE9viation utile. - </p> - <p> - <a class="target" name="frontiere"><h2>Classes fronti\xE8res</h2></a> - </p> - <p> - Quelque chose de tr\xE8s agr\xE9able est arriv\xE9e au loggueur en plus de devenir purement et simplement plus court. - </p> - <p> - Les seules choses dont il d\xE9pend sont maintenant des classes que nous avons \xE9crites nous-m\xEAme et qui dans les tests sont simul\xE9es : donc aucune d\xE9pendance hormis notre propre code PHP. Pas de fichier \xE0 \xE9crire ni de d\xE9clenchement via une horloge \xE0 attendre. Cela veut dire que le sc\xE9nario de test <em>log_test.php</em> va s'ex\xE9cuter aussi vite que le processeur le permet. Par contraste les classes <code>FileWriter</code> et <code>Clock</code> sont tr\xE8s proches du syst\xE8me. Plus difficile \xE0 tester puisque de vraies donn\xE9es doivent \xEAtre d\xE9plac\xE9es et valid\xE9es avec soin, souvent par des astuces ad hoc. - </p> - <p> - Notre derni\xE8re factorisation a beaucoup aid\xE9. Les classes aux fronti\xE8res de l'application et du syst\xE8me, celles qui sont difficiles \xE0 tester, sont d\xE9sormais plus courtes \xE9tant donn\xE9 que le code d'I/O a \xE9t\xE9 \xE9loign\xE9 encore plus de la logique applicative. Il existe des liens directs vers des op\xE9rations PHP : <code>FileWriter::write()</code> s'apparente \xE0 l'\xE9quivalent PHP <code>fwrite()</code> avec le fichier ouvert pour l'ajout et <code>Clock::now()</code> s'apparente lui aussi \xE0 un \xE9quivalent PHP <code>time()</code>. Primo le d\xE9bogage devient plus simple. Secundo ces classes devraient bouger moins souvent. - </p> - <p> - Si elles ne changent pas beaucoup alors il n'y a aucune raison pour continuer \xE0 en ex\xE9cuter les tests. Cela veut dire que les tests pour les classes fronti\xE8res peuvent \xEAtre d\xE9plac\xE9es vers leur propre suite de tests, laissant les autres tourner \xE0 plein r\xE9gime. En fait c'est comme \xE7a que j'ai tendance \xE0 travailler et les sc\xE9narios de test de <a href="simple_test.php">SimpleTest</a> lui-m\xEAme sont divis\xE9s de cette mani\xE8re. - </p> - <p> - Peut-\xEAtre que \xE7a ne vous para\xEEt pas beaucoup avec un test unitaire et deux tests aux fronti\xE8res, mais une application typique peut contenir vingt classes de fronti\xE8re et deux cent classes d'application. Pour continuer leur ex\xE9cution \xE0 toute vitesse, vous voudrez les tenir s\xE9par\xE9es. - </p> - <p> - De plus, un bon d\xE9veloppement passe par des d\xE9cisions de tri entre les composants \xE0 utiliser. Peut-\xEAtre, qui sait, tous ces simulacres pourront <a href="improving_design_tutorial.php">am\xE9liorer votre conception</a>. - </p> + Cela peut \xEAtre une abr\xE9viation utile. + </p> + </section> + <section name="frontiere" title="Classes fronti\xE8res"> + <p> + Quelque chose de tr\xE8s agr\xE9able est arriv\xE9e au loggueur en plus de devenir purement et simplement plus court. + </p> + <p> + Les seules choses dont il d\xE9pend sont maintenant des classes que nous avons \xE9crites nous-m\xEAme et qui dans les tests sont simul\xE9es : donc aucune d\xE9pendance hormis notre propre code PHP. Pas de fichier \xE0 \xE9crire ni de d\xE9clenchement via une horloge \xE0 attendre. Cela veut dire que le sc\xE9nario de test <em>log_test.php</em> va s'ex\xE9cuter aussi vite que le processeur le permet. Par contraste les classes <code>FileWriter</code> et <code>Clock</code> sont tr\xE8s proches du syst\xE8me. Plus difficile \xE0 tester puisque de vraies donn\xE9es doivent \xEAtre d\xE9plac\xE9es et valid\xE9es avec soin, souvent par des astuces ad hoc. + </p> + <p> + Notre derni\xE8re factorisation a beaucoup aid\xE9. Les classes aux fronti\xE8res de l'application et du syst\xE8me, celles qui sont difficiles \xE0 tester, sont d\xE9sormais plus courtes \xE9tant donn\xE9 que le code d'I/O a \xE9t\xE9 \xE9loign\xE9 encore plus de la logique applicative. Il existe des liens directs vers des op\xE9rations PHP : <code>FileWriter::write()</code> s'apparente \xE0 l'\xE9quivalent PHP <code>fwrite()</code> avec le fichier ouvert pour l'ajout et <code>Clock::now()</code> s'apparente lui aussi \xE0 un \xE9quivalent PHP <code>time()</code>. Primo le d\xE9bogage devient plus simple. Secundo ces classes devraient bouger moins souvent. + </p> + <p> + Si elles ne changent pas beaucoup alors il n'y a aucune raison pour continuer \xE0 en ex\xE9cuter les tests. Cela veut dire que les tests pour les classes fronti\xE8res peuvent \xEAtre d\xE9plac\xE9es vers leur propre suite de tests, laissant les autres tourner \xE0 plein r\xE9gime. En fait c'est comme \xE7a que j'ai tendance \xE0 travailler et les sc\xE9narios de test de <a href="simple_test.php">SimpleTest</a> lui-m\xEAme sont divis\xE9s de cette mani\xE8re. + </p> + <p> + Peut-\xEAtre que \xE7a ne vous para\xEEt pas beaucoup avec un test unitaire et deux tests aux fronti\xE8res, mais une application typique peut contenir vingt classes de fronti\xE8re et deux cent classes d'application. Pour continuer leur ex\xE9cution \xE0 toute vitesse, vous voudrez les tenir s\xE9par\xE9es. + </p> + <p> + De plus, un bon d\xE9veloppement passe par des d\xE9cisions de tri entre les composants \xE0 utiliser. Peut-\xEAtre, qui sait, tous ces simulacres pourront <a href="improving_design_tutorial.php">am\xE9liorer votre conception</a>. + </p> + </section> </content> <internal> Modified: simpletest/trunk/docs/source/fr/display_subclass_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/fr/display_subclass_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/fr/display_subclass_tutorial.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -2,17 +2,17 @@ <page title="Changer l'affichage du test" here="Changer l'affichage du test"> <long_title>Tutorial de test unitaire en PHP - Sous-classer l'affichage du test</long_title> <content> - <p> - Le composant affichage de SimpleTest est en fait la derni\xE8re partie \xE0 d\xE9velopper. Des morceaux de la section suivante changeront prochainement et -- avec optimisme -- des composants d'affichage plus sophistiqu\xE9s seront \xE9crits, mais pour l'instant si un affichage minime n'est pas suffisant, voici comment r\xE9aliser le votre. - </p> - <p> - <a class="target" name="succ\xE8s"><h2>Je veux voir les succ\xE8s !</h2></a> - </p> - <p> - Bon d'accord, voici comment. - </p> - <p> - Nous devons cr\xE9er une sous-classe de l'affichage utilis\xE9e, dans notre cas il s'agit de <code>HtmlReporter</code>. La classe <code>HtmlReporter</code> est situ\xE9 dans le fichier <em>simpletest/reporter.php</em> : pour l'instant elle a l'interface suivante... + <introduction> + <p> + Le composant affichage de SimpleTest est en fait la derni\xE8re partie \xE0 d\xE9velopper. Des morceaux de la section suivante changeront prochainement et -- avec optimisme -- des composants d'affichage plus sophistiqu\xE9s seront \xE9crits, mais pour l'instant si un affichage minime n'est pas suffisant, voici comment r\xE9aliser le votre. + </p> + </introduction> + <section name="succ\xE8s" title="Je veux voir les succ\xE8s !"> + <p> + Bon d'accord, voici comment. + </p> + <p> + Nous devons cr\xE9er une sous-classe de l'affichage utilis\xE9e, dans notre cas il s'agit de <code>HtmlReporter</code>. La classe <code>HtmlReporter</code> est situ\xE9 dans le fichier <em>simpletest/reporter.php</em> : pour l'instant elle a l'interface suivante... <php><![CDATA[ class HtmlReporter extends TestDisplay { public TestHtmlDisplay() { ... } @@ -30,38 +30,37 @@ public integer getTestCaseProgress { ... } } ]]></php> - Voici ce que les m\xE9thodes pertinentes veulent dire. Vous pouvez consulter la <a href="reporter_documentation.php#html">liste compl\xE8te ici</a> si cela vous int\xE9resse. - <ul class="api"> - <li> - <code>HtmlReporter()</code><br /> - est le constructeur. Notez qu'un test unitaire initie le lien vers l'affichage plut\xF4t que l'inverse. L'affichage est un r\xE9ceptacle passif des \xE9v\xE8nements de test. Cela permet une adaptation facile de l'affichage pour d'autres syst\xE8mes de test en dehors des tests unitaires comme la surveillance de serveurs par exemple. Autre avantage, un test unitaire peut \xE9crire vers plus d'un affichage \xE0 la fois. - </li> - <li> - <code>void paintFail(string $message)</code><br /> - peint un \xE9chec. Voir ci-dessous. - </li> - <li> - <code>void paintPass(string \$message)</code><br /> - ne fait rien par d\xE9faut. C'est cette m\xE9thode que nous allons modifier. - </li> - <li> - <code>string _getCss()</code><br /> - renvoie le style CSS - via une cha\xEEne - pour la m\xE9thode d'ent\xEAte de la page. Des styles compl\xE9mentaires peuvent \xEAtre ajout\xE9s ici. - </li> - <li> - <code>array getTestList()</code><br /> - est une m\xE9thode commode pour des sous-classes. Elle liste l'embo\xEEtement courant des tests via une liste de noms de test. Le premier, le test embo\xEEt\xE9 le plus profond\xE9ment, est le premier dans la liste et la m\xE9thode du test courant sera la derni\xE8re. - </li> - </ul> - </p> - <p> - Pour afficher les succ\xE8s nous avons juste besoin que la m\xE9thode <code>paintPass()</code> se comporte comme <code>paintFail()</code>. Bien s\xFBr nous n'allons pas modifier l'original. Nous allons juste cr\xE9er une sous-classe. - </p> - <p> - <a class="target" name="sous-classe"><h2>Une sous-classe d'affichage</h2></a> - </p> - <p> - Premi\xE8rement nous allons cr\xE9er un fichier <em>tests/show_passes.php</em> dans notre projet de log et y placer cette classe vide... + Voici ce que les m\xE9thodes pertinentes veulent dire. Vous pouvez consulter la <a href="reporter_documentation.php#html">liste compl\xE8te ici</a> si cela vous int\xE9resse. + <ul class="api"> + <li> + <code>HtmlReporter()</code><br /> + est le constructeur. Notez qu'un test unitaire initie le lien vers l'affichage plut\xF4t que l'inverse. L'affichage est un r\xE9ceptacle passif des \xE9v\xE8nements de test. Cela permet une adaptation facile de l'affichage pour d'autres syst\xE8mes de test en dehors des tests unitaires comme la surveillance de serveurs par exemple. Autre avantage, un test unitaire peut \xE9crire vers plus d'un affichage \xE0 la fois. + </li> + <li> + <code>void paintFail(string $message)</code><br /> + peint un \xE9chec. Voir ci-dessous. + </li> + <li> + <code>void paintPass(string \$message)</code><br /> + ne fait rien par d\xE9faut. C'est cette m\xE9thode que nous allons modifier. + </li> + <li> + <code>string _getCss()</code><br /> + renvoie le style CSS - via une cha\xEEne - pour la m\xE9thode d'ent\xEAte de la page. Des styles compl\xE9mentaires peuvent \xEAtre ajout\xE9s ici. + </li> + <li> + <code>array getTestList()</code><br /> + est une m\xE9thode commode pour des sous-classes. Elle liste l'embo\xEEtement courant des tests via une liste de noms de test. Le premier, le test embo\xEEt\xE9 le plus profond\xE9ment, est le premier dans la liste et la m\xE9thode du test courant sera la derni\xE8re. + </li> + </ul> + </p> + <p> + Pour afficher les succ\xE8s nous avons juste besoin que la m\xE9thode <code>paintPass()</code> se comporte comme <code>paintFail()</code>. Bien s\xFBr nous n'allons pas modifier l'original. Nous allons juste cr\xE9er une sous-classe. + </p> + </section> + <section name="sous-classe" title="Une sous-classe d'affichage"> + <p> + Premi\xE8rement nous allons cr\xE9er un fichier <em>tests/show_passes.php</em> dans notre projet de log et y placer cette classe vide... <php><![CDATA[ <strong><?php if (! defined('SIMPLE_TEST')) { @@ -77,7 +76,7 @@ } ?></strong> ]]></php> - Une rapide mais attentive lecture du <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/simpletest/simpletest/reporter.php?content-type=text/vnd.viewcvs-markup">code de SimpleTest</a> indique que l'impl\xE9mentation de <code>paintFail()</code> ressemble \xE0... + Une rapide mais attentive lecture du <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/simpletest/simpletest/reporter.php?content-type=text/vnd.viewcvs-markup">code de SimpleTest</a> indique que l'impl\xE9mentation de <code>paintFail()</code> ressemble \xE0... <php><![CDATA[ function paintFail($message) { parent::paintFail($message); @@ -88,7 +87,7 @@ print "->$message<br />\n"; } ]]></php> - Essentiellement elle s'encha\xEEne \xE0 la version du parent, que nous devons aussi r\xE9aliser pour garantir le m\xE9nage, et ensuite imprime une trace calcul\xE9e \xE0 partir de la liste des tests courants. Par contre elle perd au passage le nom du test du premier niveau. Etant donn\xE9 qu'il est identique pour chaque test, ce serait un peu trop d'informations. En la transposant dans notre nouvelle classe... + Essentiellement elle s'encha\xEEne \xE0 la version du parent, que nous devons aussi r\xE9aliser pour garantir le m\xE9nage, et ensuite imprime une trace calcul\xE9e \xE0 partir de la liste des tests courants. Par contre elle perd au passage le nom du test du premier niveau. Etant donn\xE9 qu'il est identique pour chaque test, ce serait un peu trop d'informations. En la transposant dans notre nouvelle classe... <php><![CDATA[ class ShowPasses extends HtmlReporter { @@ -106,7 +105,7 @@ }</strong> } ]]></php> - Pour l'instant tout roule. Maintenant pour utiliser notre nouvelle classe, nous allons modifier notre fichier <em>tests/all_tests.php</em>... + Pour l'instant tout roule. Maintenant pour utiliser notre nouvelle classe, nous allons modifier notre fichier <em>tests/all_tests.php</em>... <php><![CDATA[ <?php if (! defined('SIMPLE_TEST')) { @@ -121,19 +120,19 @@ $test->run(<strong>new ShowPasses()</strong>); ?> ]]></php> - Nous pouvons le lancer pour voir le r\xE9sultat de notre bricolage... - <div class="demo"> - <h1>All tests</h1> - Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> - Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> - Pass: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> - Pass: log_test.php->Log class test->testcreatingnewfile->File created<br /> - Pass: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - Pass: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>6</strong> passes and <strong>0</strong> fails.</div> - </div> - Joli, mais pas encore digne d'une m\xE9daille d'or. Nous avons perdu un peu d'information au passage. L'affichage du <code>span.pass</code> n'est pas styl\xE9 en CSS, mais nous pouvons l'ajouter en modifiant une autre m\xE9thode... + Nous pouvons le lancer pour voir le r\xE9sultat de notre bricolage... + <div class="demo"> + <h1>All tests</h1> + Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> + Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> + Pass: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> + Pass: log_test.php->Log class test->testcreatingnewfile->File created<br /> + Pass: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + Pass: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>6</strong> passes and <strong>0</strong> fails.</div> + </div> + Joli, mais pas encore digne d'une m\xE9daille d'or. Nous avons perdu un peu d'information au passage. L'affichage du <code>span.pass</code> n'est pas styl\xE9 en CSS, mais nous pouvons l'ajouter en modifiant une autre m\xE9thode... <php><![CDATA[ class ShowPasses extends HtmlReporter { @@ -155,23 +154,24 @@ }</strong> } ]]></php> - Si vous ajoutez le code au fur et \xE0 mesure, vous verrez l'ajout du style dans le code source du r\xE9sultat via le navigateur. A l'oeil, l'affichage devrait ressembler \xE0... - <div class="demo"> - <h1>All tests</h1> - <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->File created<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>6</strong> passes and <strong>0</strong> fails.</div> - </div> - Certains pr\xE9f\xE8rent voir les succ\xE8s quand ils travaillent sur le code; le sentiment de travail achev\xE9 est sympathique apr\xE8s tout. Une fois que vous commencez \xE0 naviguer de haut en bas pour trouver les erreurs, assez vite vous en comprendrez le c\xF4t\xE9 obscur. - </p> - <p> - Essayez les deux m\xE9thodes pour d\xE9terminer votre pr\xE9f\xE9rence. Nous allons le laisser tel que pour l'\xE9tape qui approche : <a href="mock_objects_tutorial.php">les objets fantaisie</a>. Il s'agit du premier outil de test qui ajoute des tests additionnels : il sera utile de voir ce qui se passe dans les coulisses. - </p> + Si vous ajoutez le code au fur et \xE0 mesure, vous verrez l'ajout du style dans le code source du r\xE9sultat via le navigateur. A l'oeil, l'affichage devrait ressembler \xE0... + <div class="demo"> + <h1>All tests</h1> + <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->File created<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>6</strong> passes and <strong>0</strong> fails.</div> + </div> + Certains pr\xE9f\xE8rent voir les succ\xE8s quand ils travaillent sur le code; le sentiment de travail achev\xE9 est sympathique apr\xE8s tout. Une fois que vous commencez \xE0 naviguer de haut en bas pour trouver les erreurs, assez vite vous en comprendrez le c\xF4t\xE9 obscur. + </p> + <p> + Essayez les deux m\xE9thodes pour d\xE9terminer votre pr\xE9f\xE9rence. Nous allons le laisser tel que pour l'\xE9tape qui approche : <a href="mock_objects_tutorial.php">les objets fantaisie</a>. Il s'agit du premier outil de test qui ajoute des tests additionnels : il sera utile de voir ce qui se passe dans les coulisses. + </p> + </section> </content> <internal> <link> Modified: simpletest/trunk/docs/source/fr/first_test_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/fr/first_test_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/fr/first_test_tutorial.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -2,20 +2,20 @@ <page title="Cr\xE9er un nouveau de sc\xE9nario de test" here="Tutorial : les tests unitaires en PHP"> <long_title>Tutorial sur les tests unitaires en PHP - Cr\xE9er un exemple de sc\xE9nario de test en PHP</long_title> <content> - <p> - Si vous d\xE9butez avec les tests unitaires, il est recommand\xE9 d'essayer le code au fur et \xE0 mesure. Il n'y pas grand chose \xE0 taper et vous sentirez le rythme de la programmation pilot\xE9e par les tests. - </p> - <p> - Pour ex\xE9cuter les exemples tels quels, vous aurez besoin de cr\xE9er un nouveau r\xE9pertoire et d'y installer trois dossiers : <em>classes</em>, <em>tests</em> et <em>temp</em>. D\xE9zippez le framework <a href="simple_test.php">SimpleTest</a> dans le dossier <em>tests</em> et assurez vous que votre serveur web puisse atteindre ces endroits. - </p> - <p> - <a class="target" name="nouveau"><h2>Un nouveau sc\xE9nario de test</h2></a> - </p> - <p> - L'exemple dans <a local="{{simple_test}}">l'introduction rapide</a> comprenait les tests unitaires d'une simple classe de log. Dans ce tutorial \xE0 propos de Simple Test, je vais essayer de raconter toute l'histoire du d\xE9veloppement de cette classe. Cette classe PHP est courte et simple : au cours de cette introduction, elle recevra beaucoup plus d'attention que dans le cadre d'un d\xE9veloppement de production. Nous verrons que derri\xE8re son apparente simplicit\xE9 se cachent des choix de conception \xE9tonnamment difficiles. - </p> - <p> - Peut-\xEAtre que ces choix sont trop difficiles ? Plut\xF4t que d'essayer de penser \xE0 tout en amont, je vais commencer par poser une exigence : nous voulons \xE9crire des messages dans un fichier. Ces messages doivent \xEAtre ajout\xE9s en fin de fichier s'il existe. Plus tard nous aurons besoin de priorit\xE9s, de filtres et d'autres choses encore, mais nous pla\xE7ons l'\xE9criture dans un fichier au coeur de nos pr\xE9occupations. Nous ne penserons \xE0 rien d'autres par peur de confusion. OK, commen\xE7ons par \xE9crire un test... + <introduction> + <p> + Si vous d\xE9butez avec les tests unitaires, il est recommand\xE9 d'essayer le code au fur et \xE0 mesure. Il n'y pas grand chose \xE0 taper et vous sentirez le rythme de la programmation pilot\xE9e par les tests. + </p> + <p> + Pour ex\xE9cuter les exemples tels quels, vous aurez besoin de cr\xE9er un nouveau r\xE9pertoire et d'y installer trois dossiers : <em>classes</em>, <em>tests</em> et <em>temp</em>. D\xE9zippez le framework <a href="simple_test.php">SimpleTest</a> dans le dossier <em>tests</em> et assurez vous que votre serveur web puisse atteindre ces endroits. + </p> + </introduction> + <section name="nouveau" title="Un nouveau sc\xE9nario de test"> + <p> + L'exemple dans <a local="{{simple_test}}">l'introduction rapide</a> comprenait les tests unitaires d'une simple classe de log. Dans ce tutorial \xE0 propos de Simple Test, je vais essayer de raconter toute l'histoire du d\xE9veloppement de cette classe. Cette classe PHP est courte et simple : au cours de cette introduction, elle recevra beaucoup plus d'attention que dans le cadre d'un d\xE9veloppement de production. Nous verrons que derri\xE8re son apparente simplicit\xE9 se cachent des choix de conception \xE9tonnamment difficiles. + </p> + <p> + Peut-\xEAtre que ces choix sont trop difficiles ? Plut\xF4t que d'essayer de penser \xE0 tout en amont, je vais commencer par poser une exigence : nous voulons \xE9crire des messages dans un fichier. Ces messages doivent \xEAtre ajout\xE9s en fin de fichier s'il existe. Plus tard nous aurons besoin de priorit\xE9s, de filtres et d'autres choses encore, mais nous pla\xE7ons l'\xE9criture dans un fichier au coeur de nos pr\xE9occupations. Nous ne penserons \xE0 rien d'autres par peur de confusion. OK, commen\xE7ons par \xE9crire un test... <php><![CDATA[ <strong><?php if (! defined('SIMPLE_TEST')) { @@ -36,22 +36,22 @@ $test->run(new HtmlReporter()); ?></strong> ]]></php> - Pas \xE0 pas, voici ce qu'il veut dire. - </p> - <p> - La constante <code>SIMPLE_TEST</code> contient le chemin vers les classes de Simple Test \xE0 partir de ce fichier. Les classes pourraient \xEAtre plac\xE9es dans le path du fichier <em>php.ini</em> mais si vous \xEAtes sur un serveur mutualis\xE9, vous n'y aurez probablement pas acc\xE8s. Pour que tout le monde soit content, le chemin est d\xE9clar\xE9 explicitement dans le script de test. Plus tard nous verrons comment tout finira au m\xEAme endroit. - </p> - <p> - Demander la librairie <em>unit_tester.php</em> est assez \xE9vident mais qu'est-ce que ce fichier <em>reporter.php</em> ? Les librairies Simple Test sont une bo\xEEte \xE0 outils pour cr\xE9er votre propre suite de tests standardis\xE9s. Elles peuvent \xEAtre utilis\xE9es "telles quelles" sans probl\xE8me, mais elles sont constitu\xE9es de plusieurs \xE9l\xE9ments qui ont besoin d'\xEAtre assembl\xE9s les uns aux autres. Le composant pour l'affichage est situ\xE9 dans <em>reporter.php</em>. Probablement qu'un jour vous \xE9crirez le v\xF4tre : c'est pourquoi son inclusion est optionnelle. Simple Test contient une classe d'affichage, fonctionnelle mais basique : elle s'appelle <code>HtmlReporter</code>. Elle peut enregistrer des informations sur les tests : d\xE9but, fin, erreur, r\xE9ussite ou \xE9chec. Elle affiche cette information le plus rapidement possible au cas o\xF9 le code de test planterait et masquerait le lieu de l'\xE9chec. - </p> - <p> - Les tests eux-m\xEAmes sont rassembl\xE9s dans une classe de sc\xE9nario de test. Cette derni\xE8re est typiquement une extension de la classe <code>UnitTestCase</code>. Quand le test est ex\xE9cut\xE9, elle cherche les m\xE9thodes commen\xE7ant par "test" et les lancent. Notre seule m\xE9thode de test pour l'instant est appell\xE9e <code>testCreatingNewFile()</code> mais elle est encore vide. - </p> - <p> - Une m\xE9thode vide ne fait rien. Nous avons besoin d'y placer du code. La classe <code>UnitTestCase</code> g\xE9n\xE8re des \xE9v\xE8nements de test \xE0 son ex\xE9cution : ces \xE9v\xE8nements sont envoy\xE9s vers un observateur. La m\xE9thode <code>UnitTestCase::run()</code> lancent tous les tests de la classe. - </p> - <p> - Et pour ajouter du code de test... + Pas \xE0 pas, voici ce qu'il veut dire. + </p> + <p> + La constante <code>SIMPLE_TEST</code> contient le chemin vers les classes de Simple Test \xE0 partir de ce fichier. Les classes pourraient \xEAtre plac\xE9es dans le path du fichier <em>php.ini</em> mais si vous \xEAtes sur un serveur mutualis\xE9, vous n'y aurez probablement pas acc\xE8s. Pour que tout le monde soit content, le chemin est d\xE9clar\xE9 explicitement dans le script de test. Plus tard nous verrons comment tout finira au m\xEAme endroit. + </p> + <p> + Demander la librairie <em>unit_tester.php</em> est assez \xE9vident mais qu'est-ce que ce fichier <em>reporter.php</em> ? Les librairies Simple Test sont une bo\xEEte \xE0 outils pour cr\xE9er votre propre suite de tests standardis\xE9s. Elles peuvent \xEAtre utilis\xE9es "telles quelles" sans probl\xE8me, mais elles sont constitu\xE9es de plusieurs \xE9l\xE9ments qui ont besoin d'\xEAtre assembl\xE9s les uns aux autres. Le composant pour l'affichage est situ\xE9 dans <em>reporter.php</em>. Probablement qu'un jour vous \xE9crirez le v\xF4tre : c'est pourquoi son inclusion est optionnelle. Simple Test contient une classe d'affichage, fonctionnelle mais basique : elle s'appelle <code>HtmlReporter</code>. Elle peut enregistrer des informations sur les tests : d\xE9but, fin, erreur, r\xE9ussite ou \xE9chec. Elle affiche cette information le plus rapidement possible au cas o\xF9 le code de test planterait et masquerait le lieu de l'\xE9chec. + </p> + <p> + Les tests eux-m\xEAmes sont rassembl\xE9s dans une classe de sc\xE9nario de test. Cette derni\xE8re est typiquement une extension de la classe <code>UnitTestCase</code>. Quand le test est ex\xE9cut\xE9, elle cherche les m\xE9thodes commen\xE7ant par "test" et les lancent. Notre seule m\xE9thode de test pour l'instant est appell\xE9e <code>testCreatingNewFile()</code> mais elle est encore vide. + </p> + <p> + Une m\xE9thode vide ne fait rien. Nous avons besoin d'y placer du code. La classe <code>UnitTestCase</code> g\xE9n\xE8re des \xE9v\xE8nements de test \xE0 son ex\xE9cution : ces \xE9v\xE8nements sont envoy\xE9s vers un observateur. La m\xE9thode <code>UnitTestCase::run()</code> lancent tous les tests de la classe. + </p> + <p> + Et pour ajouter du code de test... <php><![CDATA[ <?php if (! defined('SIMPLE_TEST')) { @@ -77,62 +77,61 @@ $test->run(new HtmlReporter()); ?> ]]></php> - </p> - <p> - Vous pensez probablement que \xE7a repr\xE9sente beaucoup de code pour un unique test et je suis d'accord avec vous. Ne vous inqui\xE9tez pas. Il s'agit d'un co\xFBt fixe et \xE0 partir de maintenant nous pouvons ajouter des tests : une ligne ou presque \xE0 chaque fois. Parfois moins en utilisant des artefacts de test que nous d\xE9couvrirons plus tard. - </p> - <p> - Nous devons maintenant prendre nos premi\xE8res d\xE9cisions. Notre fichier de test s'appelle <em>log_test.php</em> (n'importe quel nom ferait l'affaire) : nous le pla\xE7ons dans un dossier appel\xE9 <em>tests</em> (partout ailleurs serait aussi bien). Notre fichier de code s'appelle <em>log.php</em> : c'est son contenu que nous allons tester. Je l'ai plac\xE9 dans notre dossier <em>classes</em> : cela veut-il dire que nous construisons une classe ? - </p> - <p> - Pour cet exemple, la r\xE9ponse est oui, mais le testeur unitaire n'est pas restreint aux tests de classe. C'est juste que le code orient\xE9 objet est plus facile \xE0 d\xE9pecer et \xE0 remodeler. Ce n'est pas par hasard si la conduite de tests fins via les tests unitaires est apparue au sein de la communaut\xE9 OO. - </p> - <p> - Le test en lui-m\xEAme est minimal. Tout d'abord il \xE9limine tout autre fichier de test qui serait encore pr\xE9sent. Les d\xE9cisions de conception arrivent ensuite en rafale. Notre classe s'appelle <code>Log</code> : elle passe le chemin du fichier au constructeur. Nous cr\xE9ons le log et nous lui envoyons aussit\xF4t un message en utilisant la m\xE9thode <code>message()</code>. L'originalit\xE9 dans le nommage n'est pas une caract\xE9ristique d\xE9sirable chez un d\xE9veloppeur informatique : c'est triste mais c'est comme \xE7a. - </p> - <p> - La plus petite unit\xE9 d'un test mmm... heu... unitaire est l'assertion. Ici nous voulons nous assurer que le fichier log auquel nous venons d'envoyer un message a bel et bien \xE9t\xE9 cr\xE9\xE9. <code>UnitTestCase::assertTrue()</code> enverra un \xE9v\xE8nement r\xE9ussite si la condition \xE9valu\xE9e est vraie ou un \xE9chec dans le cas contraire. Nous pouvons avoir un ensemble d'assertions diff\xE9rentes et encore plus si nous \xE9tendons nos sc\xE9narios de test classique. Voici la liste... - <table><tbody> - <tr><td><code>assertTrue($x)</code></td><td>Echoue si $x est faux</td></tr> - <tr><td><code>assertFalse($x)</code></td><td>Echoue si $x est vrai</td></tr> - <tr><td><code>assertNull($x)</code></td><td>Echoue si $x est initialis\xE9</td></tr> - <tr><td><code>assertNotNull($x)</code></td><td>Echoue si $x n'est pas initialis\xE9</td></tr> - <tr><td><code>assertIsA($x, $t)</code></td><td>Echoue si $x n'est pas de la classe ou du type $t</td></tr> - <tr><td><code>assertEqual($x, $y)</code></td><td>Echoue si $x == $y est faux</td></tr> - <tr><td><code>assertNotEqual($x, $y)</code></td><td>Echoue si $x == $y est vrai</td></tr> - <tr><td><code>assertIdentical($x, $y)</code></td><td>Echoue si $x === $y est faux</td></tr> - <tr><td><code>assertNotIdentical($x, $y)</code></td><td>Echoue si $x === $y est vrai</td></tr> - <tr><td><code>assertReference($x, $y)</code></td><td>Echoue sauf si $x et $y sont la m\xEAme variable</td></tr> - <tr><td><code>assertCopy($x, $y)</code></td><td>Echoue si $x et $y sont la m\xEAme variable</td></tr> - <tr><td><code>assertWantedPattern($p, $x)</code></td><td>Echoue sauf si l'expression rationnelle $p capture $x</td></tr> - <tr><td><code>assertNoUnwantedPattern($p, $x)</code></td><td>Echoue si l'expression rationnelle $p capture $x</td></tr> - <tr><td><code>assertNoErrors()</code></td><td>Echoue si une erreur PHP arrive</td></tr> - <tr><td><code>assertError($x)</code></td><td>Echoue si aucune erreur ou message incorrect de PHP n'arrive</td></tr> - </tbody></table> - </p> - <p> - Nous sommes d\xE9sormais pr\xEAt \xE0 lancer notre script de test en le passant dans le navigateur. Qu'est-ce qui devrait arriver ? Il devrait planter... - <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> - La raison ? Nous n'avons pas encore cr\xE9\xE9 <em>log.php</em>. - </p> - <p> - Mais attendez une minute, c'est idiot ! Ne me dites pas qu'il faut cr\xE9er un test sans \xE9crire le code \xE0 tester auparavant... - </p> - <p> - <a class="target" name="tdd"><h2>D\xE9veloppement pilot\xE9 par les tests</h2></a> - </p> - <p> - Co-inventeur de l'<a href="http://www.extremeprogramming.org/">Extreme Programming</a>, Kent Beck a lanc\xE9 un autre manifeste. Le livre est appel\xE9 <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321146530/ref=lib_dp_TFCV/102-2696523-7458519?v=glance&s=books&vi=reader#reader-link">Test Driven Development</a> (D\xE9veloppement Pilot\xE9 par les Tests) - ou TDD et \xE9l\xE8ve les tests unitaires \xE0 une position \xE9lev\xE9e de la conception. En quelques mots, vous \xE9crivez d'abord un petit test et seulement ensuite le code qui passe ce test. N'importe quel bout de code. Juste pour qu'il passe. - </p> - <p> - Vous \xE9crivez un autre test et puis de nouveau du code qui passe. Vous aurez alors un peu de duplication et g\xE9n\xE9ralement du code pas tr\xE8s propre. Vous remaniez (factorisez) ce code-l\xE0 en vous assurant que les tests continuent \xE0 passer : vous ne pouvez rien casser. Une fois que le code est le plus propre possible vous \xEAtes pr\xEAt \xE0 ajouter des nouvelles fonctionnalit\xE9s. Il suffit juste de rajouter des nouveaux tests et de recommencer le cycle une nouvelle fois. - - </p> - <p> - Il s'agit d'une approche assez radicale et j'ai parfois l'impression qu'elle est incompl\xE8te. Mais il s'agit d'un moyen efficace pour expliquer un testeur unitaire ! Il se trouve que nous avons un test qui \xE9choue, pour ne pas dire qu'il plante : l'heure est venue d'\xE9crire du code dans <em>log.php</em>... + </p> + <p> + Vous pensez probablement que \xE7a repr\xE9sente beaucoup de code pour un unique test et je suis d'accord avec vous. Ne vous inqui\xE9tez pas. Il s'agit d'un co\xFBt fixe et \xE0 partir de maintenant nous pouvons ajouter des tests : une ligne ou presque \xE0 chaque fois. Parfois moins en utilisant des artefacts de test que nous d\xE9couvrirons plus tard. + </p> + <p> + Nous devons maintenant prendre nos premi\xE8res d\xE9cisions. Notre fichier de test s'appelle <em>log_test.php</em> (n'importe quel nom ferait l'affaire) : nous le pla\xE7ons dans un dossier appel\xE9 <em>tests</em> (partout ailleurs serait aussi bien). Notre fichier de code s'appelle <em>log.php</em> : c'est son contenu que nous allons tester. Je l'ai plac\xE9 dans notre dossier <em>classes</em> : cela veut-il dire que nous construisons une classe ? + </p> + <p> + Pour cet exemple, la r\xE9ponse est oui, mais le testeur unitaire n'est pas restreint aux tests de classe. C'est juste que le code orient\xE9 objet est plus facile \xE0 d\xE9pecer et \xE0 remodeler. Ce n'est pas par hasard si la conduite de tests fins via les tests unitaires est apparue au sein de la communaut\xE9 OO. + </p> + <p> + Le test en lui-m\xEAme est minimal. Tout d'abord il \xE9limine tout autre fichier de test qui serait encore pr\xE9sent. Les d\xE9cisions de conception arrivent ensuite en rafale. Notre classe s'appelle <code>Log</code> : elle passe le chemin du fichier au constructeur. Nous cr\xE9ons le log et nous lui envoyons aussit\xF4t un message en utilisant la m\xE9thode <code>message()</code>. L'originalit\xE9 dans le nommage n'est pas une caract\xE9ristique d\xE9sirable chez un d\xE9veloppeur informatique : c'est triste mais c'est comme \xE7a. + </p> + <p> + La plus petite unit\xE9 d'un test mmm... heu... unitaire est l'assertion. Ici nous voulons nous assurer que le fichier log auquel nous venons d'envoyer un message a bel et bien \xE9t\xE9 cr\xE9\xE9. <code>UnitTestCase::assertTrue()</code> enverra un \xE9v\xE8nement r\xE9ussite si la condition \xE9valu\xE9e est vraie ou un \xE9chec dans le cas contraire. Nous pouvons avoir un ensemble d'assertions diff\xE9rentes et encore plus si nous \xE9tendons nos sc\xE9narios de test classique. Voici la liste... + <table><tbody> + <tr><td><code>assertTrue($x)</code></td><td>Echoue si $x est faux</td></tr> + <tr><td><code>assertFalse($x)</code></td><td>Echoue si $x est vrai</td></tr> + <tr><td><code>assertNull($x)</code></td><td>Echoue si $x est initialis\xE9</td></tr> + <tr><td><code>assertNotNull($x)</code></td><td>Echoue si $x n'est pas initialis\xE9</td></tr> + <tr><td><code>assertIsA($x, $t)</code></td><td>Echoue si $x n'est pas de la classe ou du type $t</td></tr> + <tr><td><code>assertEqual($x, $y)</code></td><td>Echoue si $x == $y est faux</td></tr> + <tr><td><code>assertNotEqual($x, $y)</code></td><td>Echoue si $x == $y est vrai</td></tr> + <tr><td><code>assertIdentical($x, $y)</code></td><td>Echoue si $x === $y est faux</td></tr> + <tr><td><code>assertNotIdentical($x, $y)</code></td><td>Echoue si $x === $y est vrai</td></tr> + <tr><td><code>assertReference($x, $y)</code></td><td>Echoue sauf si $x et $y sont la m\xEAme variable</td></tr> + <tr><td><code>assertCopy($x, $y)</code></td><td>Echoue si $x et $y sont la m\xEAme variable</td></tr> + <tr><td><code>assertWantedPattern($p, $x)</code></td><td>Echoue sauf si l'expression rationnelle $p capture $x</td></tr> + <tr><td><code>assertNoUnwantedPattern($p, $x)</code></td><td>Echoue si l'expression rationnelle $p capture $x</td></tr> + <tr><td><code>assertNoErrors()</code></td><td>Echoue si une erreur PHP arrive</td></tr> + <tr><td><code>assertError($x)</code></td><td>Echoue si aucune erreur ou message incorrect de PHP n'arrive</td></tr> + </tbody></table> + </p> + <p> + Nous sommes d\xE9sormais pr\xEAt \xE0 lancer notre script de test en le passant dans le navigateur. Qu'est-ce qui devrait arriver ? Il devrait planter... + <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> + La raison ? Nous n'avons pas encore cr\xE9\xE9 <em>log.php</em>. + </p> + <p> + Mais attendez une minute, c'est idiot ! Ne me dites pas qu'il faut cr\xE9er un test sans \xE9crire le code \xE0 tester auparavant... + </p> + </section> + <section name="tdd" title="D\xE9veloppement pilot\xE9 par les tests"> + <p> + Co-inventeur de l'<a href="http://www.extremeprogramming.org/">Extreme Programming</a>, Kent Beck a lanc\xE9 un autre manifeste. Le livre est appel\xE9 <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321146530/ref=lib_dp_TFCV/102-2696523-7458519?v=glance&s=books&vi=reader#reader-link">Test Driven Development</a> (D\xE9veloppement Pilot\xE9 par les Tests) + ou TDD et \xE9l\xE8ve les tests unitaires \xE0 une position \xE9lev\xE9e de la conception. En quelques mots, vous \xE9crivez d'abord un petit test et seulement ensuite le code qui passe ce test. N'importe quel bout de code. Juste pour qu'il passe. + </p> + <p> + Vous \xE9crivez un autre test et puis de nouveau du code qui passe. Vous aurez alors un peu de duplication et g\xE9n\xE9ralement du code pas tr\xE8s propre. Vous remaniez (factorisez) ce code-l\xE0 en vous assurant que les tests continuent \xE0 passer : vous ne pouvez rien casser. Une fois que le code est le plus propre possible vous \xEAtes pr\xEAt \xE0 ajouter des nouvelles fonctionnalit\xE9s. Il suffit juste de rajouter des nouveaux tests et de recommencer le cycle une nouvelle fois. + + </p> + <p> + Il s'agit d'une approche assez radicale et j'ai parfois l'impression qu'elle est incompl\xE8te. Mais il s'agit d'un moyen efficace pour expliquer un testeur unitaire ! Il se trouve que nous avons un test qui \xE9choue, pour ne pas dire qu'il plante : l'heure est venue d'\xE9crire du code dans <em>log.php</em>... <php><![CDATA[ <strong><?php @@ -146,14 +145,14 @@ } ?></strong> ]]></php> - Il s'agit l\xE0 du minimum que nous puissions faire pour \xE9viter une erreur fatale de PHP. Et maintenant la r\xE9ponse devient... - <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>0</strong> passes and <strong>1</strong> fails.</div> - </div> - "testoflogging" a \xE9chou\xE9. Parmi les d\xE9fauts de PHP on trouve cette f\xE2cheuse tendance \xE0 transformer int\xE9rieurement les noms de classes et de m\xE9thodes en minuscules. SimpleTest utilise ces noms par d\xE9faut pour d\xE9crire les tests mais nous pouvons les remplacer par nos propres noms. + Il s'agit l\xE0 du minimum que nous puissions faire pour \xE9viter une erreur fatale de PHP. Et maintenant la r\xE9ponse devient... + <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>0</strong> passes and <strong>1</strong> fails.</div> + </div> + "testoflogging" a \xE9chou\xE9. Parmi les d\xE9fauts de PHP on trouve cette f\xE2cheuse tendance \xE0 transformer int\xE9rieurement les noms de classes et de m\xE9thodes en minuscules. SimpleTest utilise ces noms par d\xE9faut pour d\xE9crire les tests mais nous pouvons les remplacer par nos propres noms. <php><![CDATA[ class TestOfLogging extends UnitTestCase { function TestOfLogging() {<strong> @@ -167,20 +166,20 @@ } } ]]></php> - Ce qui donne... - <div class="demo"> - <h1>Log class test</h1> - <span class="fail">Fail</span>: testcreatingnewfile->File created.<br /> - <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete. - <strong>0</strong> passes and <strong>1</strong> fails.</div> - </div> - Par contre pour le nom des m\xE9thodes il n'y a rien \xE0 faire, d\xE9sol\xE9. - </p> - <p> - Les messages d'un test comme ceux-ci ressemblent \xE0 bien des \xE9gards \xE0 des commentaires de code. Certains ne jurent que par eux, d'autres au contraire les bannissent purement et simplement en les consid\xE9rant aussi encombrants qu'inutiles. Pour ma part, je me situe quelque part au milieu. - </p> - <p> - Pour que le test passe, nous pourrions nous contenter de cr\xE9er le fichier dans le constructeur de <code>Log</code>. Cette technique "en faisant semblant" est tr\xE8s utile pour v\xE9rifier que le test fonctionne pendant les passages difficiles. Elle le devient encore plus si vous sortez d'un passage avec des tests ayant \xE9chou\xE9s et que vous voulez juste v\xE9rifier de ne pas avoir oubli\xE9 un truc b\xEAte. Nous n'allons pas aussi lentement donc... + Ce qui donne... + <div class="demo"> + <h1>Log class test</h1> + <span class="fail">Fail</span>: testcreatingnewfile->File created.<br /> + <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete. + <strong>0</strong> passes and <strong>1</strong> fails.</div> + </div> + Par contre pour le nom des m\xE9thodes il n'y a rien \xE0 faire, d\xE9sol\xE9. + </p> + <p> + Les messages d'un test comme ceux-ci ressemblent \xE0 bien des \xE9gards \xE0 des commentaires de code. Certains ne jurent que par eux, d'autres au contraire les bannissent purement et simplement en les consid\xE9rant aussi encombrants qu'inutiles. Pour ma part, je me situe quelque part au milieu. + </p> + <p> + Pour que le test passe, nous pourrions nous contenter de cr\xE9er le fichier dans le constructeur de <code>Log</code>. Cette technique "en faisant semblant" est tr\xE8s utile pour v\xE9rifier que le test fonctionne pendant les passages difficiles. Elle le devient encore plus si vous sortez d'un passage avec des tests ayant \xE9chou\xE9s et que vous voulez juste v\xE9rifier de ne pas avoir oubli\xE9 un truc b\xEAte. Nous n'allons pas aussi lentement donc... <php><![CDATA[ <?php class Log {<strong> @@ -198,25 +197,24 @@ } ?> ]]></php> - Au total, pas moins de 4 \xE9checs ont \xE9t\xE9 n\xE9cessaire pour passer \xE0 l'\xE9tape suivante. Je n'avais pas cr\xE9\xE9 le r\xE9pertoire temporaire, je ne lui avais pas donn\xE9 les droits d'\xE9criture, j'avais une coquille et je n'avais pas non plus ajout\xE9 ce nouveau r\xE9pertoire dans CVS. N'importe laquelle de ces erreurs aurait pu m'occuper pendant plusieurs heures si elle \xE9tait apparue plus tard mais c'est bien pour ces cas l\xE0 qu'on teste. Avec les corrections ad\xE9quates, \xE7a donne... - <div class="demo"> - <h1>Log class test</h1> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. - <strong>1</strong> passes and <strong>0</strong> fails.</div> - </div> - \xC7a marche! - </p> - <p> - Peut-\xEAtre n'aimez-vous pas le style plut\xF4t minimal de l'affichage. Les succ\xE8s ne sont pas montr\xE9s par d\xE9faut puisque g\xE9n\xE9ralement vous n'avez pas besoin de plus d'information quand vous comprenez effectivement ce qui se passe. Dans le cas contraire, pensez \xE0 \xE9crire d'autres tests. - </p> - <p> - D'accord, c'est assez strict. Si vous voulez aussi voir les succ\xE8s alors vous pouvez <a local="display_subclass_tutorial">cr\xE9er une sous-classe de <code>HtmlReporter</code></a> et l'utiliser pour les tests. M\xEAme moi j'aime bien ce confort parfois. - </p> - <p> - <a class="target" name="doc"><h2>Les tests comme documentation</h2></a> - </p> - <p> - Il y a une nuance ici. Nous ne voulons pas cr\xE9er de fichier avant d'avoir effectivement envoy\xE9 de message. Plut\xF4t que d'y r\xE9fl\xE9chir trop longtemps, nous allons juste ajouter un test pour \xE7a. + Au total, pas moins de 4 \xE9checs ont \xE9t\xE9 n\xE9cessaire pour passer \xE0 l'\xE9tape suivante. Je n'avais pas cr\xE9\xE9 le r\xE9pertoire temporaire, je ne lui avais pas donn\xE9 les droits d'\xE9criture, j'avais une coquille et je n'avais pas non plus ajout\xE9 ce nouveau r\xE9pertoire dans CVS. N'importe laquelle de ces erreurs aurait pu m'occuper pendant plusieurs heures si elle \xE9tait apparue plus tard mais c'est bien pour ces cas l\xE0 qu'on teste. Avec les corrections ad\xE9quates, \xE7a donne... + <div class="demo"> + <h1>Log class test</h1> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. + <strong>1</strong> passes and <strong>0</strong> fails.</div> + </div> + \xC7a marche! + </p> + <p> + Peut-\xEAtre n'aimez-vous pas le style plut\xF4t minimal de l'affichage. Les succ\xE8s ne sont pas montr\xE9s par d\xE9faut puisque g\xE9n\xE9ralement vous n'avez pas besoin de plus d'information quand vous comprenez effectivement ce qui se passe. Dans le cas contraire, pensez \xE0 \xE9crire d'autres tests. + </p> + <p> + D'accord, c'est assez strict. Si vous voulez aussi voir les succ\xE8s alors vous pouvez <a local="display_subclass_tutorial">cr\xE9er une sous-classe de <code>HtmlReporter</code></a> et l'utiliser pour les tests. M\xEAme moi j'aime bien ce confort parfois. + </p> + </section> + <section name="doc" title="Les tests comme documentation"> + <p> + Il y a une nuance ici. Nous ne voulons pas cr\xE9er de fichier avant d'avoir effectivement envoy\xE9 de message. Plut\xF4t que d'y r\xE9fl\xE9chir trop longtemps, nous allons juste ajouter un test pour \xE7a. <php><![CDATA[ class TestOfLogging extends UnitTestCase { function TestOfLogging() { @@ -231,20 +229,21 @@ } } ]]></php> - ...et d\xE9couvrir que \xE7a marche d\xE9j\xE0... - <div class="demo"> - <h1>Log class test</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> - En fait je savais que \xE7a allait \xEAtre le cas. J'ajoute ce test de confirmation tout d'abord pour garder l'esprit tranquille, mais aussi pour documenter ce comportement. Ce petit test suppl\xE9mentaire dans son contexte en dit plus long qu'un sc\xE9nario utilisateur d'une douzaine de lignes ou qu'un diagramme UML complet. Que la suite de tests devienne une source de documentation est un effet secondaire assez agr\xE9able. - </p> - <p> - Devrions-nous supprimer le fichier temporaire \xE0 la fin du test ? Par habitude, je le fais une fois que j'en ai termin\xE9 avec la m\xE9thode de test et qu'elle marche. Je n'ai pas envie de valider du code qui laisse des restes de fichiers de test tra\xEEner apr\xE8s un test. Mais je ne le fais pas non plus pendant que j'\xE9cris le code. Peut-\xEAtre devrais-je, mais parfois j'ai besoin de voir ce qui se passe : on retrouve cet aspect confort \xE9voqu\xE9 plus haut. - </p> - <p> - Dans un v\xE9ritable projet, nous avons habituellement plus qu'un unique sc\xE9nario de test : c'est pourquoi nous allons regarder comment <a local="group_test_tutorial">grouper des tests dans des suites de tests</a>. - </p> + ...et d\xE9couvrir que \xE7a marche d\xE9j\xE0... + <div class="demo"> + <h1>Log class test</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> + En fait je savais que \xE7a allait \xEAtre le cas. J'ajoute ce test de confirmation tout d'abord pour garder l'esprit tranquille, mais aussi pour documenter ce comportement. Ce petit test suppl\xE9mentaire dans son contexte en dit plus long qu'un sc\xE9nario utilisateur d'une douzaine de lignes ou qu'un diagramme UML complet. Que la suite de tests devienne une source de documentation est un effet secondaire assez agr\xE9able. + </p> + <p> + Devrions-nous supprimer le fichier temporaire \xE0 la fin du test ? Par habitude, je le fais une fois que j'en ai termin\xE9 avec la m\xE9thode de test et qu'elle marche. Je n'ai pas envie de valider du code qui laisse des restes de fichiers de test tra\xEEner apr\xE8s un test. Mais je ne le fais pas non plus pendant que j'\xE9cris le code. Peut-\xEAtre devrais-je, mais parfois j'ai besoin de voir ce qui se passe : on retrouve cet aspect confort \xE9voqu\xE9 plus haut. + </p> + <p> + Dans un v\xE9ritable projet, nous avons habituellement plus qu'un unique sc\xE9nario de test : c'est pourquoi nous allons regarder comment <a local="group_test_tutorial">grouper des tests dans des suites de tests</a>. + </p> + </section> </content> <internal> <link>Cr\xE9er un <a href="#nouveau">nouveau sc\xE9nario de test</a>.</link> Modified: simpletest/trunk/docs/source/fr/gain_control_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/fr/gain_control_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/fr/gain_control_tutorial.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -2,27 +2,28 @@ <page title="Prendre le contr\xF4le des tests" here="Prendre le contr\xF4le des tests"> <long_title>Tutorial de test unitaire en PHP - Isoler les variables pendant le test</long_title> <content> - <p> - Pour tester un module de code vous avez besoin d'avoir un contr\xF4le tr\xE8s pr\xE9cis sur son environnement. Si quelque chose change dans les coulisses, par exemple dans un fichier de configuration, alors les tests peuvent \xE9chouer de fa\xE7on inattendue. Il ne s'agirait plus d'un test de code sans \xE9quivoque et pourrait vous faire perdre des heures pr\xE9cieuses \xE0 la recherche d'erreurs dans un code qui fonctionne. Alors qu'il s'agit d'un probl\xE8me de configuration qui plante le test en question. Au mieux vos sc\xE9narios de test deviennent de plus en plus compliqu\xE9s afin de prendre en compte toutes les variations possibles. - </p> - <p> - <a class="target" name="temps"><h2>Contr\xF4ler le temps</h2></a> - <p> - </p> - Il y a souvent beaucoup de variables \xE9videntes qui peuvent affecter un sc\xE9nario de test unitaire, d'autant plus dans un environnement de d\xE9veloppement web dans lequel PHP a ses aises. Parmi celles-ci, on trouve les param\xE8tres de connexion \xE0 la base de donn\xE9es et ceux de configuration, les droits de fichier et les ressources r\xE9seau, etc. L'\xE9chec ou la mauvaise installation de l'un ou l'autre de ces composants cassera la suite de test. Est-ce que nous devons ajouter des tests pour valider l'installation de ces composants ? C'est une bonne id\xE9e mais si vous les placez dans les tests du module de code vous aller commencer \xE0 encombrer votre code de test avec des d\xE9tails hors de propos avec la t\xE2che en cours. Ils doivent \xEAtre plac\xE9s dans leur propre groupe de tests. - </p> - <p> - Par contre un autre probl\xE8me reste : nos machines de d\xE9veloppement doivent aussi avoir tous les composants syst\xE8me d'install\xE9s avant l'ex\xE9cution de la suite de test. Et vos tests s'ex\xE9cuteront plus lentement. - </p> - <p> - Devant un tel dilemme, nous cr\xE9erons souvent des versions enveloppantes des classes qui g\xE8rent ces ressources. Les vilains d\xE9tails de ces ressources sont ensuite cod\xE9s une seule fois. J'aime bien appeler ces classes des "classes fronti\xE8re" \xE9tant donn\xE9 qu'elles existent en bordure de l'application, l'interface entre votre application et le reste du syst\xE8me. Ces classes fronti\xE8re sont - dans le meilleur des cas - simul\xE9es pendant les tests par des versions de simulacre. Elles s'ex\xE9cutent plus rapidement et sont souvent appel\xE9es "bouchon serveur [Ndt : Server Stubs]" ou dans leur forme plus g\xE9n\xE9rique "objet fantaisie [Ndt : Mock Objects]". Envelopper et bouchonner chacune de ces ressources permet d'\xE9conomiser pas mal de temps. - </p> - <p> - Un des facteurs souvent n\xE9glig\xE9s reste le temps. Par exemple, pour tester l'expiration d'une session des codeurs vont souvent temporairement en caler la dur\xE9e \xE0 une valeur tr\xE8s courte, disons 2 secondes, et ensuite effectuer un <code>sleep(3)</code> : ils estiment alors que la session a expir\xE9e. Sauf que cette op\xE9ration ajoute 3 secondes \xE0 la suite de test : il s'agit souvent de beaucoup de code en plus pour rendre la classe de session aussi mall\xE9able. Plus simple serait d'avoir un moyen d'avancer l'horloge arbitrairement. De contr\xF4ler le temps. - </p> - <p> - <a class="target" name="horloge"><h2>Une classe horloge</h2></a> - Une nouvelle fois, nous allons effectuer notre conception d'une enveloppe d'horloge via l'\xE9criture de tests. Premi\xE8rement nous ajoutons un sc\xE9nario de test d'horloge dans notre suite de test <em>tests/all_tests.php</em>... + <introduction> + <p> + Pour tester un module de code vous avez besoin d'avoir un contr\xF4le tr\xE8s pr\xE9cis sur son environnement. Si quelque chose change dans les coulisses, par exemple dans un fichier de configuration, alors les tests peuvent \xE9chouer de fa\xE7on inattendue. Il ne s'agirait plus d'un test de code sans \xE9quivoque et pourrait vous faire perdre des heures pr\xE9cieuses \xE0 la recherche d'erreurs dans un code qui fonctionne. Alors qu'il s'agit d'un probl\xE8me de configuration qui plante le test en question. Au mieux vos sc\xE9narios de test deviennent de plus en plus compliqu\xE9s afin de prendre en compte toutes les variations possibles. + </p> + </introduction> + <section name="temps" title="Contr\xF4ler le temps"> + <p> + Il y a souvent beaucoup de variables \xE9videntes qui peuvent affecter un sc\xE9nario de test unitaire, d'autant plus dans un environnement de d\xE9veloppement web dans lequel PHP a ses aises. Parmi celles-ci, on trouve les param\xE8tres de connexion \xE0 la base de donn\xE9es et ceux de configuration, les droits de fichier et les ressources r\xE9seau, etc. L'\xE9chec ou la mauvaise installation de l'un ou l'autre de ces composants cassera la suite de test. Est-ce que nous devons ajouter des tests pour valider l'installation de ces composants ? C'est une bonne id\xE9e mais si vous les placez dans les tests du module de code vous aller commencer \xE0 encombrer votre code de test avec des d\xE9tails hors de propos avec la t\xE2che en cours. Ils doivent \xEAtre plac\xE9s dans leur propre groupe de tests. + </p> + <p> + Par contre un autre probl\xE8me reste : nos machines de d\xE9veloppement doivent aussi avoir tous les composants syst\xE8me d'install\xE9s avant l'ex\xE9cution de la suite de test. Et vos tests s'ex\xE9cuteront plus lentement. + </p> + <p> + Devant un tel dilemme, nous cr\xE9erons souvent des versions enveloppantes des classes qui g\xE8rent ces ressources. Les vilains d\xE9tails de ces ressources sont ensuite cod\xE9s une seule fois. J'aime bien appeler ces classes des "classes fronti\xE8re" \xE9tant donn\xE9 qu'elles existent en bordure de l'application, l'interface entre votre application et le reste du syst\xE8me. Ces classes fronti\xE8re sont - dans le meilleur des cas - simul\xE9es pendant les tests par des versions de simulacre. Elles s'ex\xE9cutent plus rapidement et sont souvent appel\xE9es "bouchon serveur [Ndt : Server Stubs]" ou dans leur forme plus g\xE9n\xE9rique "objet fantaisie [Ndt : Mock Objects]". Envelopper et bouchonner chacune de ces ressources permet d'\xE9conomiser pas mal de temps. + </p> + <p> + Un des facteurs souvent n\xE9glig\xE9s reste le temps. Par exemple, pour tester l'expiration d'une session des codeurs vont souvent temporairement en caler la dur\xE9e \xE0 une valeur tr\xE8s courte, disons 2 secondes, et ensuite effectuer un <code>sleep(3)</code> : ils estiment alors que la session a expir\xE9e. Sauf que cette op\xE9ration ajoute 3 secondes \xE0 la suite de test : il s'agit souvent de beaucoup de code en plus pour rendre la classe de session aussi mall\xE9able. Plus simple serait d'avoir un moyen d'avancer l'horloge arbitrairement. De contr\xF4ler le temps. + </p> + </section> + <section name="horloge" title="Une classe horloge"> + <p> + Une nouvelle fois, nous allons effectuer notre conception d'une enveloppe d'horloge via l'\xE9criture de tests. Premi\xE8rement nous ajoutons un sc\xE9nario de test d'horloge dans notre suite de test <em>tests/all_tests.php</em>... <php><![CDATA[ <?php if (! defined('SIMPLE_TEST')) { @@ -39,7 +40,7 @@ $test->run(new HtmlReporter()); ?> ]]></php> - Ensuite nous cr\xE9ons le sc\xE9nario de test dans un nouveau fichier <em>tests/clock_test.php</em>... + Ensuite nous cr\xE9ons le sc\xE9nario de test dans un nouveau fichier <em>tests/clock_test.php</em>... <php><![CDATA[ <strong><?php require_once('../classes/clock.php'); @@ -57,14 +58,14 @@ } ?></strong> ]]></php> - Notre unique test pour le moment, c'est que notre nouvelle class <code>Clock</code> se comporte comme un simple substitut de la fonction <code>time()</code> en PHP. L'autre m\xE9thode tient lieu d'emploi. C'est notre <em>chose \xE0 faire</em> en quelque sorte. Nous ne lui avons pas donn\xE9e de test parce que \xE7a casserait notre rythme. Nous \xE9crirons cette fonctionnalit\xE9 de d\xE9calage dans le temps une fois que nous serons au vert. Pour le moment nous ne sommes \xE9videmment pas dans le vert... - <div class="demo"> - <br /> - <b>Fatal error</b>: Failed opening required '../classes/clock.php' (include_path='') in - <b>/home/marcus/projects/lastcraft/tutorial_tests/tests/clock_test.php</b> on line <b>2</b> - <br /> - </div> - Nous cr\xE9ons un fichier <em>classes/clock.php</em> comme ceci... + Notre unique test pour le moment, c'est que notre nouvelle class <code>Clock</code> se comporte comme un simple substitut de la fonction <code>time()</code> en PHP. L'autre m\xE9thode tient lieu d'emploi. C'est notre <em>chose \xE0 faire</em> en quelque sorte. Nous ne lui avons pas donn\xE9e de test parce que \xE7a casserait notre rythme. Nous \xE9crirons cette fonctionnalit\xE9 de d\xE9calage dans le temps une fois que nous serons au vert. Pour le moment nous ne sommes \xE9videmment pas dans le vert... + <div class="demo"> + <br /> + <b>Fatal error</b>: Failed opening required '../classes/clock.php' (include_path='') in + <b>/home/marcus/projects/lastcraft/tutorial_tests/tests/clock_test.php</b> on line <b>2</b> + <br /> + </div> + Nous cr\xE9ons un fichier <em>classes/clock.php</em> comme ceci... <php><![CDATA[ <strong><?php class Clock { @@ -77,14 +78,14 @@ } ?></strong> ]]></php> - De la sorte nous reprenons le cours du code. - <div class="demo"> - <h1>All tests</h1> - <span class="fail">Fail</span>: Clock class test->testclocktellstime->[NULL: ] should be equal to [integer: 1050257362]<br /> - <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">3/3 test cases complete. - <strong>4</strong> passes and <strong>1</strong> fails.</div> - </div> - Facile \xE0 corriger... + De la sorte nous reprenons le cours du code. + <div class="demo"> + <h1>All tests</h1> + <span class="fail">Fail</span>: Clock class test->testclocktellstime->[NULL: ] should be equal to [integer: 1050257362]<br /> + <div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">3/3 test cases complete. + <strong>4</strong> passes and <strong>1</strong> fails.</div> + </div> + Facile \xE0 corriger... <php><![CDATA[ class Clock { @@ -96,16 +97,16 @@ } } ]]></php> - Et nous revoici dans le vert... - <div class="demo"> - <h1>All tests</h1> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>5</strong> passes and <strong>0</strong> fails.</div> - </div> - Il y a juste un petit probl\xE8me. L'horloge pourrait basculer pendant l'assertion et cr\xE9er un \xE9cart d'une seconde. Les probabilit\xE9s sont assez faibles mais s'il devait y avoir beaucoup de tests de chronom\xE9trage nous finirions avec une suite de test qui serait erratique et forc\xE9ment presque inutile. Nous nous <a href="subclass_tutorial.php">y attaquerons bient\xF4t</a> et pour l'instant nous l'ajoutons dans la liste des "choses \xE0 faire". - </p> - <p> - Le test d'avancement ressemble \xE0... + Et nous revoici dans le vert... + <div class="demo"> + <h1>All tests</h1> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>5</strong> passes and <strong>0</strong> fails.</div> + </div> + Il y a juste un petit probl\xE8me. L'horloge pourrait basculer pendant l'assertion et cr\xE9er un \xE9cart d'une seconde. Les probabilit\xE9s sont assez faibles mais s'il devait y avoir beaucoup de tests de chronom\xE9trage nous finirions avec une suite de test qui serait erratique et forc\xE9ment presque inutile. Nous nous <a href="subclass_tutorial.php">y attaquerons bient\xF4t</a> et pour l'instant nous l'ajoutons dans la liste des "choses \xE0 faire". + </p> + <p> + Le test d'avancement ressemble \xE0... <php><![CDATA[ class TestOfClock extends UnitTestCase { function TestOfClock() { @@ -122,7 +123,7 @@ }</strong> } ]]></php> - Le code pour arriver au vert est direct : il suffit d'ajouter un d\xE9calage de temps. + Le code pour arriver au vert est direct : il suffit d'ajouter un d\xE9calage de temps. <php><![CDATA[ class Clock {<strong> var $_offset;</strong> @@ -140,13 +141,13 @@ }</strong> } ]]></php> - </p> - <p> - <a class="target" name="nettoyer"><h2>Nettoyer le test de groupe</h2></a> - Notre fichier <em>all_tests.php</em> contient des r\xE9p\xE9titions dont nous pourrions nous d\xE9barrasser. Nous devons ajouter manuellement tous nos sc\xE9narios de test depuis chaque fichier inclus. C'est possible de les enlever mais avec les pr\xE9cautions suivantes. La classe <code>GroupTest</code> inclue une m\xE9thode bien pratique appel\xE9e <code>addTestFile()</code> qui prend un fichier PHP comme param\xE8tre. Ce m\xE9canisme prend note de toutes les classes : elle inclut le fichier et ensuite regarde toutes les classes nouvellement cr\xE9\xE9es. S'il y a des filles de <code>TestCase</code> elles sont ajout\xE9es au nouveau test de groupe. - </p> - <p> - Voici notre suite de test remani\xE9e en appliquant cette m\xE9thode... + </p> + <p> + <a class="target" name="nettoyer"><h2>Nettoyer le test de groupe</h2></a> + Notre fichier <em>all_tests.php</em> contient des r\xE9p\xE9titions dont nous pourrions nous d\xE9barrasser. Nous devons ajouter manuellement tous nos sc\xE9narios de test depuis chaque fichier inclus. C'est possible de les enlever mais avec les pr\xE9cautions suivantes. La classe <code>GroupTest</code> inclue une m\xE9thode bien pratique appel\xE9e <code>addTestFile()</code> qui prend un fichier PHP comme param\xE8tre. Ce m\xE9canisme prend note de toutes les classes : elle inclut le fichier et ensuite regarde toutes les classes nouvellement cr\xE9\xE9es. S'il y a des filles de <code>TestCase</code> elles sont ajout\xE9es au nouveau test de groupe. + </p> + <p> + Voici notre suite de test remani\xE9e en appliquant cette m\xE9thode... <php><![CDATA[ <?php if (! defined('SIMPLE_TEST')) { @@ -161,20 +162,21 @@ $test->run(new HtmlReporter()); ?> ]]></php> - Les inconv\xE9niants sont les suivants... - <ol> - <li> - Si le fichier de test a d\xE9j\xE0 \xE9t\xE9 inclus, aucune nouvelle classe ne sera ajout\xE9e au groupe. - </li> - <li> - Si le fichier de test contient d'autres classes reli\xE9es \xE0 <code>TestCase</code> alors celles-ci aussi seront ajout\xE9 au test de groupe. - </li> - </ol> - Dans nos test nous n'avons que des sc\xE9narios dans les fichiers de test et en plus nous avons supprim\xE9 leur inclusion du script <em>all_tests.php</em> : nous sommes donc en r\xE8gle. C'est la situation la plus commune. - </p> - <p> - Nous devrions corriger au plus vite le petit probl\xE8me de d\xE9calage possible sur l'horloge : c'est ce que nous <a href="subclass_tutorial.php">faisons ensuite</a>. - </p> + Les inconv\xE9niants sont les suivants... + <ol> + <li> + Si le fichier de test a d\xE9j\xE0 \xE9t\xE9 inclus, aucune nouvelle classe ne sera ajout\xE9e au groupe. + </li> + <li> + Si le fichier de test contient d'autres classes reli\xE9es \xE0 <code>TestCase</code> alors celles-ci aussi seront ajout\xE9 au test de groupe. + </li> + </ol> + Dans nos test nous n'avons que des sc\xE9narios dans les fichiers de test et en plus nous avons supprim\xE9 leur inclusion du script <em>all_tests.php</em> : nous sommes donc en r\xE8gle. C'est la situation la plus commune. + </p> + <p> + Nous devrions corriger au plus vite le petit probl\xE8me de d\xE9calage possible sur l'horloge : c'est ce que nous <a href="subclass_tutorial.php">faisons ensuite</a>. + </p> + </section> </content> <internal> <link>Le <a href="#temps">temps</a> est souvent une variable n\xE9glig\xE9e dans les tests.</link> Modified: simpletest/trunk/docs/source/fr/group_test_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/fr/group_test_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) +++ simpletest/trunk/docs/source/fr/group_test_tutorial.xml 2008-02-18 12:42:54 UTC (rev 1659) @@ -4,14 +4,14 @@ Tutorial de test unitaire PHP - Grouper des tests unitaires et exemples d'\xE9criture de sc\xE9narios de tests </long_title> <content> - <p> - Pour encha\xEEner nous allons remplir des blancs et cr\xE9er une suite de tests. - </p> - <p> - <a class="target" name="autre"><h2>Un autre test</h2></a> - </p> - <p> - Ajouter un autre test peut \xEAtre aussi simple qu'ajouter une nouvelle m\xE9thode \xE0 un sc\xE9nario de test... + <introduction> + <p> + Pour encha\xEEner nous allons remplir des blancs et cr\xE9er une suite de tests. + </p> + </introduction> + <section name="autre" title="Un autre test"> + <p> + Ajouter un autre test peut \xEAtre aussi simple qu'ajouter une nouvelle m\xE9thode \xE0 un sc\xE9nario de test... <php><![CDATA[ class TestOfLogging extends UnitTestCase { function TestOfLogging() { @@ -38,22 +38,22 @@ }</strong> } ]]></php> - La m\xE9thode du sc\xE9nario de test <code>assertWantedPattern()</code> utilise les expressions rationnelles Perl pour v\xE9rifier qu'une cha\xEEne respecte un certain motif. - </p> - <p> - Tout ce que nous faisons dans ce nouveau test, c'est \xE9crire une ligne dans un fichier, puis la lire, le tout deux fois de suite. Nous souhaitons simplement v\xE9rifier que le loggueur ajoute le texte \xE0 la fin plut\xF4t qu'\xE9craser les donn\xE9es d\xE9j\xE0 existantes. Quelque peu p\xE9dant, mais apr\xE8s tout il s'agit d'un tutorial ! - </p> - <p> - De toute fa\xE7on ce test passe directement... - <div class="demo"> - <h1>Log class test</h1> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. - <strong>4</strong> passes and <strong>0</strong> fails.</div> - </div> - Notre code contient actuellement beaucoup de r\xE9p\xE9titions, nous devons effacer le fichier de test avant et apr\xE8s chaque test. De m\xEAme que <a href="http://www.junit.org/">JUnit</a>, SimpleTest utilise les m\xE9thodes <code>setUp()</code> et <code>tearDown()</code> qui sont ex\xE9cut\xE9es respectivement avant et apr\xE8s chaque test. La suppression du fichier est commune \xE0 tous les tests : nous devrions donc y mettre cette op\xE9ration. - </p> - <p> - Nos tests sont verts donc nous pouvons faire un peu de remaniement... + La m\xE9thode du sc\xE9nario de test <code>assertWantedPattern()</code> utilise les expressions rationnelles Perl pour v\xE9rifier qu'une cha\xEEne respecte un certain motif. + </p> + <p> + Tout ce que nous faisons dans ce nouveau test, c'est \xE9crire une ligne dans un fichier, puis la lire, le tout deux fois de suite. Nous souhaitons simplement v\xE9rifier que le loggueur ajoute le texte \xE0 la fin plut\xF4t qu'\xE9craser les donn\xE9es d\xE9j\xE0 existantes. Quelque peu p\xE9dant, mais apr\xE8s tout il s'agit d'un tutorial ! + </p> + <p> + De toute fa\xE7on ce test passe directement... + <div class="demo"> + <h1>Log class test</h1> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. + <strong>4</strong> passes and <strong>0</strong> fails.</div> + </div> + Notre code contient actuellement beaucoup de r\xE9p\xE9titions, nous devons effacer le fichier de test avant et apr\xE8s chaque test. De m\xEAme que <a href="http://www.junit.org/">JUnit</a>, SimpleTest utilise les m\xE9thodes <code>setUp()</code> et <code>tearDown()</code> qui sont ex\xE9cut\xE9es respectivement avant et apr\xE8s chaque test. La suppression du fichier est commune \xE0 tous les tests : nous devrions donc y mettre cette op\xE9ration. + </p> + <p> + Nos tests sont verts donc nous pouvons faire un peu de remaniement... <php><![CDATA[ class TestOfLogging extends UnitTestCase { function TestOfLogging() { @@ -82,7 +82,7 @@ }</strong> } ]]></php> @@ Diff output truncated at 100000 characters. @@ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pp11@us...> - 2008-02-18 11:14:29
|
Revision: 1658 http://simpletest.svn.sourceforge.net/simpletest/?rev=1658&view=rev Author: pp11 Date: 2008-02-18 03:14:26 -0800 (Mon, 18 Feb 2008) Log Message: ----------- Second go at the rewriting of the docs using "autorun" Modified Paths: -------------- simpletest/trunk/docs/source/en/boundary_classes_tutorial.xml simpletest/trunk/docs/source/en/browser_documentation.xml simpletest/trunk/docs/source/en/display_subclass_tutorial.xml simpletest/trunk/docs/source/en/experimental_autorun.xml simpletest/trunk/docs/source/en/experimental_dom_tester.xml simpletest/trunk/docs/source/en/experimental_intro.xml simpletest/trunk/docs/source/en/experimental_recorder.xml simpletest/trunk/docs/source/en/extension_eclipse.xml simpletest/trunk/docs/source/en/first_test_tutorial.xml simpletest/trunk/docs/source/en/gain_control_tutorial.xml simpletest/trunk/docs/source/en/group_test_tutorial.xml simpletest/trunk/docs/source/en/improving_design_tutorial.xml simpletest/trunk/docs/source/en/mock_objects_tutorial.xml simpletest/trunk/docs/source/en/reporter_documentation.xml simpletest/trunk/docs/source/en/subclass_tutorial.xml simpletest/trunk/docs/source/en/support_website.xml simpletest/trunk/docs/source/en/web_tester_documentation.xml simpletest/trunk/packages/simpletest.org/index.php simpletest/trunk/packages/simpletest.org/package.php Modified: simpletest/trunk/docs/source/en/boundary_classes_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/en/boundary_classes_tutorial.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/boundary_classes_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -5,288 +5,287 @@ class test cases </long_title> <content> - <p> - You are probably thinking that we have well and truly exhausted - the <code>Log</code> class by now and that there is - really nothing more to add. - Things are never that simple with object oriented programming, though. - You think you understand a problem and then something comes a long - that challenges your perspective and leads to an even deeper appreciation. - I thought I understood the logging class and that only the first page - of the tutorial would use it. - After that I would move on to something more complicated. - No one is more surprised than me that I still haven't got to - the bottom of it. - In fact I think I have only just figured out what a logger does. - </p> - <p> - <a class="target" name="variation"><h2>Log variations</h2></a> - </p> - <p> - Supposing that we do not want to log to a file at all. - Perhaps we want to print to the screen, write the messages to a - socket or send them to the Unix(tm) <em>syslog</em> daemon for - dispatching across the network. - How do we incorporate this variation? - </p> - <p> - Simplest is to subclass the <code>Log</code> - overriding the <code>message()</code> method - with new versions. - This will work in the short term, but there is actually something - subtle, but deeply wrong with this. - Suppose we do subclass and have loggers that write to files, - the screen and the network. - Three classes , but that is OK. - Now suppose that we want a new logging class that adds message - filtering by priority, letting only certain types of messages - through according to some configuration file. - </p> - <p> - We are stuck. If we subclass again, we have to do it for all - three classes, giving us six classes. - The amount of duplication is horrible. - </p> - <p> - So are you now wishing that PHP had multiple inheritence? - Well, here that would reduce the short term workload, but - complicate what should be a very simple class. - Multiple inheritance, even when supported, should be used - extremely carefully as all sorts of complicated entanglements - can result. - Treat it as a loaded gun. - In fact, our sudden need for it is telling us something else - perhaps - that we have gone wrong on the conceptual level. - </p> - <p> - What does a logger do? - Does it send messages to a file? - Does it send messages to a network? - Does it send messages to a screen? - Nope. - It just sends messages (full stop). - The target of those messages can be chosen when setting - up the log, but after that the - logger should be left to combine and format the message - elements as that is its real job. - We restricted ourselves by assuming that target was a filename. - </p> - <p> - <a class="target" name="writer"><h2>Abstracting a file to a writer</h2></a> - </p> - <p> - The solution to this plight is a real classic. - First we encapsulate the variation in a class as this will - add a level of indirection. - Instead of passing in the file name as a string we - will pass the "thing that we will write to" - which we will call a <code>Writer</code>. - Back to the tests... + <introduction> + <p> + You are probably thinking that we have well and truly exhausted + the <code>Log</code> class by now and that there is + really nothing more to add. + Things are never that simple with object oriented programming, though. + You think you understand a problem and then something comes a long + that challenges your perspective and leads to an even deeper appreciation. + I thought I understood the logging class and that only the first page + of the tutorial would use it. + After that I would move on to something more complicated. + No one is more surprised than me that I still haven't got to + the bottom of it. + In fact I think I have only just figured out what a logger does. + </p> + </introduction> + <section name="variation" title="Log variations"> + <p> + Supposing that we do not want to log to a file at all. + Perhaps we want to print to the screen, write the messages to a + socket or send them to the Unix(tm) <em>syslog</em> daemon for + dispatching across the network. + How do we incorporate this variation? + </p> + <p> + Simplest is to subclass the <code>Log</code> + overriding the <code>message()</code> method + with new versions. + This will work in the short term, but there is actually something + subtle, but deeply wrong with this. + Suppose we do subclass and have loggers that write to files, + the screen and the network. + Three classes , but that is OK. + Now suppose that we want a new logging class that adds message + filtering by priority, letting only certain types of messages + through according to some configuration file. + </p> + <p> + We are stuck. If we subclass again, we have to do it for all + three classes, giving us six classes. + The amount of duplication is horrible. + </p> + <p> + So are you now wishing that PHP had multiple inheritence? + Well, here that would reduce the short term workload, but + complicate what should be a very simple class. + Multiple inheritance, even when supported, should be used + extremely carefully as all sorts of complicated entanglements + can result. + Treat it as a loaded gun. + In fact, our sudden need for it is telling us something else - perhaps + that we have gone wrong on the conceptual level. + </p> + <p> + What does a logger do? + Does it send messages to a file? + Does it send messages to a network? + Does it send messages to a screen? + Nope. + It just sends messages (full stop). + The target of those messages can be chosen when setting + up the log, but after that the + logger should be left to combine and format the message + elements as that is its real job. + We restricted ourselves by assuming that target was a filename. + </p> + </section> + <section name="writer" title="Abstracting a file to a writer"> + <p> + The solution to this plight is a real classic. + First we encapsulate the variation in a class as this will + add a level of indirection. + Instead of passing in the file name as a string we + will pass the "thing that we will write to" + which we will call a <code>Writer</code>. + Back to the tests... <php><![CDATA[ <?php - require_once('../classes/log.php'); - require_once('../classes/clock.php');<strong> - require_once('../classes/writer.php');</strong> - Mock::generate('Clock'); +require_once('../classes/log.php'); +require_once('../classes/clock.php');<strong> +require_once('../classes/writer.php');</strong> +Mock::generate('Clock'); - class TestOfLogging extends UnitTestCase { - function TestOfLogging() { - $this->UnitTestCase('Log class test'); - } - function setUp() { - @unlink('../temp/test.log'); - } - function tearDown() { - @unlink('../temp/test.log'); - } - function getFileLine($filename, $index) { - $messages = file($filename); - return $messages[$index]; - } - function testCreatingNewFile() {<strong> - $log = new Log(new FileWriter('../temp/test.log'));</strong> - $this->assertFalse(file_exists('../temp/test.log'), 'Created before message'); - $log->message('Should write this to a file'); - $this->assertTrue(file_exists('../temp/test.log'), 'File created'); - } - function testAppendingToFile() {<strong> - $log = new Log(new FileWriter('../temp/test.log'));</strong> - $log->message('Test line 1'); - $this->assertWantedPattern( - '/Test line 1/', - $this->getFileLine('../temp/test.log', 0)); - $log->message('Test line 2'); - $this->assertWantedPattern( - '/Test line 2/', - $this->getFileLine('../temp/test.log', 1)); - } - function testTimestamps() { - $clock = &new MockClock($this); - $clock->setReturnValue('now', 'Timestamp');<strong> - $log = new Log(new FileWriter('../temp/test.log'));</strong> - $log->message('Test line', &$clock); - $this->assertWantedPattern( - '/Timestamp/', - $this->getFileLine('../temp/test.log', 0), - 'Found timestamp'); - } +class TestOfLogging extends UnitTestCase { + function TestOfLogging() { + $this->UnitTestCase('Log class test'); } + function setUp() { + @unlink('../temp/test.log'); + } + function tearDown() { + @unlink('../temp/test.log'); + } + function getFileLine($filename, $index) { + $messages = file($filename); + return $messages[$index]; + } + function testCreatingNewFile() {<strong> + $log = new Log(new FileWriter('../temp/test.log'));</strong> + $this->assertFalse(file_exists('../temp/test.log'), 'Created before message'); + $log->message('Should write this to a file'); + $this->assertTrue(file_exists('../temp/test.log'), 'File created'); + } + function testAppendingToFile() {<strong> + $log = new Log(new FileWriter('../temp/test.log'));</strong> + $log->message('Test line 1'); + $this->assertWantedPattern( + '/Test line 1/', + $this->getFileLine('../temp/test.log', 0)); + $log->message('Test line 2'); + $this->assertWantedPattern( + '/Test line 2/', + $this->getFileLine('../temp/test.log', 1)); + } + function testTimestamps() { + $clock = &new MockClock($this); + $clock->setReturnValue('now', 'Timestamp');<strong> + $log = new Log(new FileWriter('../temp/test.log'));</strong> + $log->message('Test line', &$clock); + $this->assertWantedPattern( + '/Timestamp/', + $this->getFileLine('../temp/test.log', 0), + 'Found timestamp'); + } +} ?> ]]></php> - I am going to do this one step at a time so as not to get - confused. - I have replaced the file names with an imaginary - <code>FileWriter</code> class from - a file <em>classes/writer.php</em>. - This will cause the tests to crash as we have not written - the writer yet. - Should we do that now? - </p> - <p> - We could, but we don't have to. - We do need to create the interface, though, or we won't be - able to mock it. - This makes <em>classes/writer.php</em> looks like... + I am going to do this one step at a time so as not to get + confused. + I have replaced the file names with an imaginary + <code>FileWriter</code> class from + a file <em>classes/writer.php</em>. + This will cause the tests to crash as we have not written + the writer yet. + Should we do that now? + </p> + <p> + We could, but we don't have to. + We do need to create the interface, though, or we won't be + able to mock it. + This makes <em>classes/writer.php</em> looks like... <php><![CDATA[ <?php - class FileWriter { +class FileWriter { - function FileWriter($file_path) { - } + function FileWriter($file_path) { + } - function write($message) { - } + function write($message) { } +} ?> ]]></php> - We need to modify the <code>Log</code> class - as well... + We need to modify the <code>Log</code> class + as well... <php><![CDATA[ <?php - require_once('../classes/clock.php');<strong> - require_once('../classes/writer.php');</strong> +require_once('../classes/clock.php');<strong> +require_once('../classes/writer.php');</strong> - class Log {<strong> - var $_writer;</strong> +class Log {<strong> + var $_writer;</strong> - function Log(<strong>&$writer</strong>) {<strong> - $this->_writer = &$writer;</strong> - } + function Log(<strong>&$writer</strong>) {<strong> + $this->_writer = &$writer;</strong> + } - function message($message, $clock = false) { - if (! is_object($clock)) { - $clock = new Clock(); - }<strong> - $this->_writer->write("[" . $clock->now() . "] $message");</strong> - } + function message($message, $clock = false) { + if (! is_object($clock)) { + $clock = new Clock(); + }<strong> + $this->_writer->write("[" . $clock->now() . "] $message");</strong> } +} ?> ]]></php> - There is not much that hasn't changed in our now even smaller - class. - The tests run, but fail at this point unless we add code to - the writer. - What do we do now? - </p> - <p> - We could start writing tests and code the - <code>FileWriter</code> class alongside, but - while we were doing this our <code>Log</code> - tests would be failing and disturbing our focus. - In fact we do not have to. - </p> - <p> - Part of our plan is to free the logging class from the file - system and there is a way to do this. - First we add a <em>tests/writer_test.php</em> so that - we have somewhere to place our test code from <em>log_test.php</em> - that we are going to shuffle around. - I won't yet add it to the <em>all_tests.php</em> file - though as it is the logging aspect we are tackling right now. - </p> - <p> - Now I have done that (honest) we remove any - tests from <em>log_test.php</em> that are not strictly logging - related and move them to <em>writer_test.php</em> for later. - We will also mock the writer so that it does not write - out to real files... + There is not much that hasn't changed in our now even smaller + class. + The tests run, but fail at this point unless we add code to + the writer. + What do we do now? + </p> + <p> + We could start writing tests and code the + <code>FileWriter</code> class alongside, but + while we were doing this our <code>Log</code> + tests would be failing and disturbing our focus. + In fact we do not have to. + </p> + <p> + Part of our plan is to free the logging class from the file + system and there is a way to do this. + First we add a <em>tests/writer_test.php</em> so that + we have somewhere to place our test code from <em>log_test.php</em> + that we are going to shuffle around. + I won't yet add it to the <em>all_tests.php</em> file + though as it is the logging aspect we are tackling right now. + </p> + <p> + Now I have done that (honest) we remove any + tests from <em>log_test.php</em> that are not strictly logging + related and move them to <em>writer_test.php</em> for later. + We will also mock the writer so that it does not write + out to real files... <php><![CDATA[ <?php - require_once('../classes/log.php'); - require_once('../classes/clock.php'); - require_once('../classes/writer.php'); - Mock::generate('Clock');<strong> - Mock::generate('FileWriter');</strong> +require_once('../classes/log.php'); +require_once('../classes/clock.php'); +require_once('../classes/writer.php'); +Mock::generate('Clock');<strong> +Mock::generate('FileWriter');</strong> - class TestOfLogging extends UnitTestCase { - function TestOfLogging() { - $this->UnitTestCase('Log class test'); - }<strong> - function testWriting() { - $clock = &new MockClock(); - $clock->setReturnValue('now', 'Timestamp'); - $writer = &new MockFileWriter($this); - $writer->expectArguments('write', array('[Timestamp] Test line')); - $writer->expectCallCount('write', 1); - $log = &new Log(\$writer); - $log->message('Test line', &$clock); - }</strong> - } +class TestOfLogging extends UnitTestCase { + function TestOfLogging() { + $this->UnitTestCase('Log class test'); + }<strong> + function testWriting() { + $clock = &new MockClock(); + $clock->setReturnValue('now', 'Timestamp'); + $writer = &new MockFileWriter($this); + $writer->expectArguments('write', array('[Timestamp] Test line')); + $writer->expectCallCount('write', 1); + $log = &new Log(\$writer); + $log->message('Test line', &$clock); + }</strong> +} ?> ]]></php> - Yes that really is the whole test case and it really is that short. - A lot has happened here... - <ol> - <li> - The requirement to create the file only when needed has - moved to the <code>FileWriter</code>. - </li> - <li> - As we are dealing with mocks, no files are actually - created and so I moved the - <code>setUp()</code> and - <code>tearDown()</code> off into the - writing tests. - </li> - <li> - The test now consists of sending a sample message and - testing the format. - </li> - </ol> - Hang on a minute, where are the assertions? - </p> - <p> - The mock objects do much more than simply behave like other - objects, they also run tests. - The <code>expectArguments()</code> - call told the mock to expect a single parameter of - the string "[Timestamp] Test line" when - the mock <code>write()</code> method is - called. - When that method is called the expected parameters are - compared with this and either a pass or a fail is sent - to the unit test as a result. - </p> - <p> - The other expectation is that <code>write()</code> - will be called only once. - Simply setting this up is not enough. - We can see all this in action by running the tests... - <div class="demo"> - <h1>All tests</h1> - <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Arguments for [write] were [String: [Timestamp] Test line]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Expected call count for [write] was [1], but got [1]<br /> - - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>4</strong> passes and <strong>0</strong> fails.</div> - </div> - </p> - <p> - We can actually shorten our test slightly more. - The mock object expectation <code>expectOnce()</code> - can actually combine the two seperate expectations... + Yes that really is the whole test case and it really is that short. + A lot has happened here... + <ol> + <li> + The requirement to create the file only when needed has + moved to the <code>FileWriter</code>. + </li> + <li> + As we are dealing with mocks, no files are actually + created and so I moved the + <code>setUp()</code> and + <code>tearDown()</code> off into the + writing tests. + </li> + <li> + The test now consists of sending a sample message and + testing the format. + </li> + </ol> + Hang on a minute, where are the assertions? + </p> + <p> + The mock objects do much more than simply behave like other + objects, they also run tests. + The <code>expectArguments()</code> + call told the mock to expect a single parameter of + the string "[Timestamp] Test line" when + the mock <code>write()</code> method is + called. + When that method is called the expected parameters are + compared with this and either a pass or a fail is sent + to the unit test as a result. + </p> + <p> + The other expectation is that <code>write()</code> + will be called only once. + Simply setting this up is not enough. + We can see all this in action by running the tests... + <div class="demo"> + <h1>All tests</h1> + <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Arguments for [write] were [String: [Timestamp] Test line]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Expected call count for [write] was [1], but got [1]<br /> + + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>4</strong> passes and <strong>0</strong> fails.</div> + </div> + </p> + <p> + We can actually shorten our test slightly more. + The mock object expectation <code>expectOnce()</code> + can actually combine the two seperate expectations... <php><![CDATA[ function testWriting() { $clock = &new MockClock(); @@ -297,69 +296,68 @@ $log->message('Test line', &$clock); } ]]></php> - This can be an effective shorthand. - </p> - <p> - <a class="target" name="boundary"><h2>Boundary classes</h2></a> - </p> - <p> - Something very nice has happened to the logger besides merely - getting smaller. - </p> - <p> - The only things it depends on now are classes that we have written - ourselves and - in the tests these are mocked and so there are no dependencies - on anything other than our own PHP code. - No writing to files or waiting for clocks to tick over. - This means that the <em>log_test.php</em> test case will - run as fast as the processor will carry it. - By contrast the <code>FileWriter</code> - and <code>Clock</code> classes are very - close to the system. - This makes them harder to test as real data must be moved - around and painstakingly confirmed, often by ad hoc tricks. - </p> - <p> - Our last refactoring has helped a lot. - The hard to test classes on the boundary of the application - and the system are now smaller as the I/O code has - been further separated from the application logic. - They are direct mappings to PHP operations: - <code>FileWriter::write()</code> maps - to PHP <code>fwrite()</code> with the - file opened for appending and - <code>Clock::now()</code> maps to - PHP <code>time()</code>. - This makes debugging easier. - It also means that these classes will change less often. - </p> - <p> - If they don't change a lot then there is no reason to - keep running the tests for them. - This means that tests for the boundary classes can be moved - off into there own test suite leaving the other unit tests - to run at full speed. - In fact this is what I tend to do and the test cases - in <a href="simple_test.php">SimpleTest</a> itself are - divided this way. - </p> - <p> - That may not sound like much with one unit test and two - boundary tests, but typical applications can have - twenty boundary classes and two hundred application - classes. - To keep these running at full speed you will want - to keep them separate. - </p> - <p> - Besides, separating off decisions of which system components - to use is good development. - Perhaps all this mocking is - <a href="improving_design_tutorial.php">improving our design</a>? - </p> + This can be an effective shorthand. + </p> + </section> + <section name="boundary" title="Boundary classes"> + <p> + Something very nice has happened to the logger besides merely + getting smaller. + </p> + <p> + The only things it depends on now are classes that we have written + ourselves and + in the tests these are mocked and so there are no dependencies + on anything other than our own PHP code. + No writing to files or waiting for clocks to tick over. + This means that the <em>log_test.php</em> test case will + run as fast as the processor will carry it. + By contrast the <code>FileWriter</code> + and <code>Clock</code> classes are very + close to the system. + This makes them harder to test as real data must be moved + around and painstakingly confirmed, often by ad hoc tricks. + </p> + <p> + Our last refactoring has helped a lot. + The hard to test classes on the boundary of the application + and the system are now smaller as the I/O code has + been further separated from the application logic. + They are direct mappings to PHP operations: + <code>FileWriter::write()</code> maps + to PHP <code>fwrite()</code> with the + file opened for appending and + <code>Clock::now()</code> maps to + PHP <code>time()</code>. + This makes debugging easier. + It also means that these classes will change less often. + </p> + <p> + If they don't change a lot then there is no reason to + keep running the tests for them. + This means that tests for the boundary classes can be moved + off into there own test suite leaving the other unit tests + to run at full speed. + In fact this is what I tend to do and the test cases + in <a href="simple_test.php">SimpleTest</a> itself are + divided this way. + </p> + <p> + That may not sound like much with one unit test and two + boundary tests, but typical applications can have + twenty boundary classes and two hundred application + classes. + To keep these running at full speed you will want + to keep them separate. + </p> + <p> + Besides, separating off decisions of which system components + to use is good development. + Perhaps all this mocking is + <a href="improving_design_tutorial.php">improving our design</a>? + </p> + </section> </content> - <internal> <link> <a href="#variation">Handling variation</a> in our logger. Modified: simpletest/trunk/docs/source/en/browser_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/browser_documentation.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/browser_documentation.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -18,15 +18,15 @@ open PHP 5 bugs from the <a href="http://www.php.net/">PHP web site</a>... <php><![CDATA[ <strong><?php - require_once('simpletest/browser.php'); +require_once('simpletest/browser.php'); - $browser = &new SimpleBrowser(); - $browser->get('http://php.net/';); - $browser->click('reporting bugs'); - $browser->click('statistics'); - $page = $browser->click('PHP 5 bugs only'); - preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches); - print $matches[1]; +$browser = &new SimpleBrowser(); +$browser->get('http://php.net/';); +$browser->click('reporting bugs'); +$browser->click('statistics'); +$page = $browser->click('PHP 5 bugs only'); +preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches); +print $matches[1]; ?></strong> ]]></php> There are simpler methods to do this particular example in PHP @@ -156,8 +156,8 @@ now be done in a <a local="unit_tester_documentation">UnitTestCase</a>. This means that we can freely mix domain object testing with the web interface... -<php><![CDATA[<strong> -class TestOfRegistration extends UnitTestCase { +<php><![CDATA[ +<strong>class TestOfRegistration extends UnitTestCase { function testNewUserAddedToAuthenticator() {</strong> $browser = &new SimpleBrowser(); $browser->get('http://my-site.com/register.php';); Modified: simpletest/trunk/docs/source/en/display_subclass_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/en/display_subclass_tutorial.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/display_subclass_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -2,27 +2,27 @@ <page title="Changing the test display" here="Showing passes"> <long_title>PHP unit testing tutorial - Subclassing the test display</long_title> <content> - <p> - The display component of SimpleTest is actually the part - to be developed last. - Some of the following section will change in the future - and hopefully more sophisticated display components will - be written, but - in the meantime if a minimal display is not enough, here - is how to roll your own. - </p> - <p> - <a class="target" name="passes"><h2>I want to see the passes!</h2></a> - </p> - <p> - Oh all right then, here's how. - </p> - <p> - We have to subclass the attached display, which in our case - is currently <code>HtmlReporter</code>. - The <code>HtmlReporter</code> class is in - the file <em>simpletest/reporter.php</em> and currently has - the following interface... + <introduction> + <p> + The display component of SimpleTest is actually the part + to be developed last. + Some of the following section will change in the future + and hopefully more sophisticated display components will + be written, but + in the meantime if a minimal display is not enough, here + is how to roll your own. + </p> + </introduction> + <section name="passes" title="I want to see the passes!"> + <p> + Oh all right then, here's how. + </p> + <p> + We have to subclass the attached display, which in our case + is currently <code>HtmlReporter</code>. + The <code>HtmlReporter</code> class is in + the file <em>simpletest/reporter.php</em> and currently has + the following interface... <php><![CDATA[ class HtmlReporter extends TestDisplay { public TestHtmlDisplay() { ... } @@ -40,80 +40,79 @@ public integer getTestCaseProgress { ... } } ]]></php> - Here is what the relevant methods mean. - You can see the - <a href="reporter_documentation.php#html">whole list here</a> - if you are interested. - <ul class="api"> - <li> - <code>HtmlReporter()</code><br /> - is the constructor. - Note that the unit test sets up the link to the display - rather than the other way around. - The display is a passive receiver of test events. - This allows easy adaption of the display for other test - systems beside unit tests, such as monitoring servers. - It also means that the unit test can write to more than - one display at a time. - </li> - <li> - <code>void paintFail(string $message)</code><br /> - paints a failure. - See below. - </li> - <li> - <code>void paintPass(string $message)</code><br /> - by default does nothing. - This is the method we will modify. - </li> - <li> - <code>string _getCss()</code><br /> - returns the CSS styles as a string for the page header - method. - Additional styles have to be appended here. - </li> - <li> - <code>array getTestList()</code><br /> - is a convenience method for subclasses. - Lists the current nesting of the tests as a list - of test names. - The first, most deeply nested test, is first in the - list and the current test method will be last. - </li> - </ul> - </p> - <p> - To show the passes we just need the - <code>paintPass()</code> method to behave - just like <code>paintFail()</code>. - Of course we won't modify the original. - We'll subclass. - </p> - <p> - <a class="target" name="subclass"><h2>A display subclass</h2></a> - </p> - <p> - Firstly we'll create a <em>tests/show_passes.php</em> file - in our logging project and then place in it this empty class... + Here is what the relevant methods mean. + You can see the + <a href="reporter_documentation.php#html">whole list here</a> + if you are interested. + <ul class="api"> + <li> + <code>HtmlReporter()</code><br /> + is the constructor. + Note that the unit test sets up the link to the display + rather than the other way around. + The display is a passive receiver of test events. + This allows easy adaption of the display for other test + systems beside unit tests, such as monitoring servers. + It also means that the unit test can write to more than + one display at a time. + </li> + <li> + <code>void paintFail(string $message)</code><br /> + paints a failure. + See below. + </li> + <li> + <code>void paintPass(string $message)</code><br /> + by default does nothing. + This is the method we will modify. + </li> + <li> + <code>string _getCss()</code><br /> + returns the CSS styles as a string for the page header + method. + Additional styles have to be appended here. + </li> + <li> + <code>array getTestList()</code><br /> + is a convenience method for subclasses. + Lists the current nesting of the tests as a list + of test names. + The first, most deeply nested test, is first in the + list and the current test method will be last. + </li> + </ul> + </p> + <p> + To show the passes we just need the + <code>paintPass()</code> method to behave + just like <code>paintFail()</code>. + Of course we won't modify the original. + We'll subclass. + </p> + </section> + <section name="subclass" title="A display subclass"> + <p> + Firstly we'll create a <em>tests/show_passes.php</em> file + in our logging project and then place in it this empty class... <php><![CDATA[ <strong><?php - if (! defined('SIMPLE_TEST')) { - define('SIMPLE_TEST', 'simpletest/'); - } - require_once(SIMPLE_TEST . 'reporter.php'); +if (! defined('SIMPLE_TEST')) { + define('SIMPLE_TEST', 'simpletest/'); +} +require_once(SIMPLE_TEST . 'reporter.php'); - class ShowPasses extends HtmlReporter { +class ShowPasses extends HtmlReporter { - function ShowPasses() { - $this->HtmlReporter(); - } + function ShowPasses() { + $this->HtmlReporter(); } +} ?></strong> ]]></php> - A quick peruse of the - <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/simpletest/simpletest/reporter.php?content-type=text/vnd.viewcvs-markup">SimpleTest code base</a> shows the - <code>paintFail()</code> implementation - at the time of writing to look like this... + A quick peruse of the + <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/simpletest/simpletest/reporter.php?content-type=text/vnd.viewcvs-markup">SimpleTest code base</a> shows the + <code>paintFail()</code> implementation + at the time of writing to look like this... <php><![CDATA[ function paintFail($message) { parent::paintFail($message); @@ -124,14 +123,14 @@ print "->$message<br />\n"; } ]]></php> - Essentially it chains to the parent's version, which we - have to do also to preserve house keeping, and then - prints a breadcrumbs trail calculated from the current test - list. - It drops the top level tests name, though. - As it is the same on every test that would be a little bit too - much information. - Transposing this to our new class... + Essentially it chains to the parent's version, which we + have to do also to preserve house keeping, and then + prints a breadcrumbs trail calculated from the current test + list. + It drops the top level tests name, though. + As it is the same on every test that would be a little bit too + much information. + Transposing this to our new class... <php><![CDATA[ class ShowPasses extends HtmlReporter { @@ -149,40 +148,40 @@ }</strong> } ]]></php> - So far so good. - Now to make use of our new class we have to modify our - <em>tests/all_tests.php</em> file... + So far so good. + Now to make use of our new class we have to modify our + <em>tests/all_tests.php</em> file... <php><![CDATA[ <?php - if (! defined('SIMPLE_TEST')) { - define('SIMPLE_TEST', 'simpletest/'); - } - require_once(SIMPLE_TEST . 'unit_tester.php');<strong> - require_once('show_passes.php');</strong> +if (! defined('SIMPLE_TEST')) { + define('SIMPLE_TEST', 'simpletest/'); +} +require_once(SIMPLE_TEST . 'unit_tester.php');<strong> +require_once('show_passes.php');</strong> - $test = &new TestSuite('All tests'); - $test->addTestFile('log_test.php'); - $test->addTestFile('clock_test.php'); - $test->run(<strong>new ShowPasses()</strong>); +$test = &new TestSuite('All tests'); +$test->addTestFile('log_test.php'); +$test->addTestFile('clock_test.php'); +$test->run(<strong>new ShowPasses()</strong>); ?> ]]></php> - We can run this to see the results of our handywork... - <div class="demo"> - <h1>All tests</h1> - Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> - Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> - Pass: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> - Pass: log_test.php->Log class test->testcreatingnewfile->File created<br /> - Pass: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - Pass: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>6</strong> passes and <strong>0</strong> fails.</div> - </div> - Nice, but no gold star. - We have lost a little formatting here. - The display does not have a CSS style for - <code>span.pass</code>, but we can add this - easily by overriding one more method... + We can run this to see the results of our handywork... + <div class="demo"> + <h1>All tests</h1> + Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> + Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> + Pass: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> + Pass: log_test.php->Log class test->testcreatingnewfile->File created<br /> + Pass: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + Pass: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>6</strong> passes and <strong>0</strong> fails.</div> + </div> + Nice, but no gold star. + We have lost a little formatting here. + The display does not have a CSS style for + <code>span.pass</code>, but we can add this + easily by overriding one more method... <php><![CDATA[ class ShowPasses extends HtmlReporter { @@ -204,33 +203,34 @@ }</strong> } ]]></php> - If you are adding the code as you go, you will see the style - appended when you do view source on the test results page in your browser. - To the eye the display itself should now look like this... - <div class="demo"> - <h1>All tests</h1> - <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> - <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->File created<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> - <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. - <strong>6</strong> passes and <strong>0</strong> fails.</div> - </div> - Some people definitely prefer to see the passes being added - as they are working on code; the feeling that you are getting - work done is nice after all. - Once you have to scroll up and down the page to find failures - though, you soon come to realise its dark side. - </p> - <p> - Try it both ways and see which you prefer. - We'll leave it in for a bit anyhow when looking at the - <a href="mock_objects_tutorial.php">mock objects coming up</a>. - This is the first test tool that generates additional tests - and it will be useful to see what is happening behind the scenes. - </p> + If you are adding the code as you go, you will see the style + appended when you do view source on the test results page in your browser. + To the eye the display itself should now look like this... + <div class="demo"> + <h1>All tests</h1> + <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->Created before message<br /> + <span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->File created<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br /> + <span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br /> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete. + <strong>6</strong> passes and <strong>0</strong> fails.</div> + </div> + Some people definitely prefer to see the passes being added + as they are working on code; the feeling that you are getting + work done is nice after all. + Once you have to scroll up and down the page to find failures + though, you soon come to realise its dark side. + </p> + <p> + Try it both ways and see which you prefer. + We'll leave it in for a bit anyhow when looking at the + <a href="mock_objects_tutorial.php">mock objects coming up</a>. + This is the first test tool that generates additional tests + and it will be useful to see what is happening behind the scenes. + </p> + </section> </content> <internal> <link> Modified: simpletest/trunk/docs/source/en/experimental_autorun.xml =================================================================== --- simpletest/trunk/docs/source/en/experimental_autorun.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/experimental_autorun.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -2,69 +2,69 @@ <page title="Running the tests, the easy way with autorun" here="Autorunning test cases"> <long_title>[experimental] Running the tests, the easy way with autorun</long_title> <content> - <div class="experimental"> - Careful : this documentation refers to un-released code. It's only available in CVS. - </div> - <p> - You started with unit testing not so long ago and - this is what you came up with... A file <em>test_of_all_modules.php</em> - containing : + <introduction> + <div class="experimental"> + Careful : this documentation refers to un-released code. It's only available in CVS. + </div> + <p> + You started with unit testing not so long ago and + this is what you came up with... A file <em>test_of_all_modules.php</em> + containing : <php><![CDATA[ <?php require_once('simpletest/unit_tester.php'); require_once('simpletest/reporter.php'); $group = new TestSuite(); -$group->addTestFile('test_of_module_ship.php'); -$group->addTestFile('test_of_module_pay.php'); +$group->addFile('test_of_module_ship.php'); +$group->addFile('test_of_module_pay.php'); $group->run(new HtmlReporter()); ?> ]]></php> - </p> - <p> - But now you have a new way of shipping your socks overseas. Easily - you just need to add a new file <em>test_of_module_ship_overseas.php</em> - to your test runner... Quickly enough, you end up with a lot of file : + </p> + <p> + But now you have a new way of shipping your socks overseas. Easily + you just need to add a new file <em>test_of_module_ship_overseas.php</em> + to your test runner... Quickly enough, you end up with a lot of file : <php><![CDATA[ <?php require_once('simpletest/unit_tester.php'); require_once('simpletest/reporter.php'); $group = new TestSuite(); -$group->addTestFile('test_of_module_ship.php');<strong> -$group->addTestFile('test_of_module_ship_overseas.php'); -$group->addTestFile('test_of_module_ship_france.php'); -$group->addTestFile('test_of_module_ship_uk.php'); -$group->addTestFile('test_of_module_ship_us.php'); +$group->addFile('test_of_module_ship.php');<strong> +$group->addFile('test_of_module_ship_overseas.php'); +$group->addFile('test_of_module_ship_france.php'); +$group->addFile('test_of_module_ship_uk.php'); +$group->addFile('test_of_module_ship_us.php'); ...</strong> -$group->addTestFile('test_of_module_pay.php'); +$group->addFile('test_of_module_pay.php'); $group->run(new HtmlReporter()); ?> ]]></php> - </p> - <p> - As you list grows, running the test suite becomes too time- - consuming : the tests are actually slowing you down while writing code. - </p> - <p> - <a class="target" name="autorun"><h2>Introducing 'autorun'</h2></a> - </p> - <p> - What we're looking for now is a way to run one test at a time - and still be able to run every one of them easily... - What if we could just write - in a console for example : - <div class="console"> - home: /$ <strong>php test_of_module_ship_us.php</strong> - </div> - and still be able to do : - <div class="console"> - home: /$ <strong>php test_of_all_modules.php</strong> - </div> - It's possible now : you just need to add one include at the top of - each test case. Your <em>test_of_module_ship_us.php</em> will - look like : + </p> + <p> + As you list grows, running the test suite becomes too time- + consuming : the tests are actually slowing you down while writing code. + </p> + </introduction> + <section name="autorun" title="Introducing 'autorun'"> + <p> + What we're looking for now is a way to run one test at a time + and still be able to run every one of them easily... + What if we could just write - in a console for example : + <div class="console"> + home: /$ <strong>php test_of_module_ship_us.php</strong> + </div> + and still be able to do : + <div class="console"> + home: /$ <strong>php test_of_all_modules.php</strong> + </div> + It's possible now : you just need to add one include at the top of + each test case. Your <em>test_of_module_ship_us.php</em> will + look like : <php><![CDATA[ <?php<strong> require_once('simpletest/autorun.php');</strong> @@ -82,15 +82,14 @@ } ?> ]]></php> - </p> - <p> - <a class="target" name="preference"><h2>Setting the prefered runner</h2></a> - </p> - <p> - PHP is mainly for web stuff : I'm guessing your first test platform is - a web browser, Firefox, Opera or Safari usually. And SimpleTest comes with - a nice HTML interface : it's the one we want to use when running one file. - We can tell our <em>test_of_module_ship_us.php</em> to use it by default : + </p> + </section> + <section name="preference" title="Setting the prefered runner"> + <p> + PHP is mainly for web stuff : I'm guessing your first test platform is + a web browser, Firefox, Opera or Safari usually. And SimpleTest comes with + a nice HTML interface : it's the one we want to use when running one file. + We can tell our <em>test_of_module_ship_us.php</em> to use it by default : <php><![CDATA[ <?php require_once('simpletest/autorun.php');<strong> @@ -109,36 +108,35 @@ } ?> ]]></php> - </p> - <p> - We get a nice green bar : - <div class="demo"> - <h1>TestSuite</h1> - <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">2/2 test cases complete: - <strong>2</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div> - </div> - </p> - <p> - <a class="target" name="autorun-for-suites"><h2>Autorun for test suites</h2></a> - </p> - <p> - So we've managed to get the time spent running the test under control - during the coding period. We now want to make sure all the tests still - pass, all the time. Or at least after every commit to the SVN (or CVS) - trunk. - </p> - <p> - Such process is called <em>continuous integration</em> : Martin Fowler writes - really well about this practice <cite>where members of a team integrate their - work frequently [...]. Each integration is verified by an automated buid - (including test) to detect integration errors as quickly as possible</cite>. - So I can just give you the link : - <a href="http://www.martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a>. - </p> - <p> - Now our post-commit hook in SVN (or Phing task if you prefer) doesn't need - the HTML reporter. We need something useful at the command line : TextReporter - to the rescue. Our <em>test_of_all_modules.php</em> becomes : + </p> + <p> + We get a nice green bar : + <div class="demo"> + <h1>TestSuite</h1> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">2/2 test cases complete: + <strong>2</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div> + </div> + </p> + </section> + <section name="autorun-for-suites" title="Autorun for test suites"> + <p> + So we've managed to get the time spent running the test under control + during the coding period. We now want to make sure all the tests still + pass, all the time. Or at least after every commit to the SVN (or CVS) + trunk. + </p> + <p> + Such process is called <em>continuous integration</em> : Martin Fowler writes + really well about this practice <cite>where members of a team integrate their + work frequently [...]. Each integration is verified by an automated buid + (including test) to detect integration errors as quickly as possible</cite>. + So I can just give you the link : + <a href="http://www.martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a>. + </p> + <p> + Now our post-commit hook in SVN (or Phing task if you prefer) doesn't need + the HTML reporter. We need something useful at the command line : TextReporter + to the rescue. Our <em>test_of_all_modules.php</em> becomes : <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -148,27 +146,28 @@ class AllTests extends TestSuite { function AllTests() { parent::TestSuite(); - $this->addTestFile('test_of_module_ship.php'); - $this->addTestFile('test_of_module_ship_overseas.php'); - $this->addTestFile('test_of_module_ship_france.php'); - $this->addTestFile('test_of_module_ship_uk.php'); - $this->addTestFile('test_of_module_ship_us.php'); + $this->addFile('test_of_module_ship.php'); + $this->addFile('test_of_module_ship_overseas.php'); + $this->addFile('test_of_module_ship_france.php'); + $this->addFile('test_of_module_ship_uk.php'); + $this->addFile('test_of_module_ship_us.php'); ... - $this->addTestFile('test_of_module_pay.php'); + $this->addFile('test_of_module_pay.php'); } } ?> ]]></php> - </p> - <p> - The results show up nicely in the console : - <div class="console"> - home: /$ php test_of_all_modules.php<br /> - <strong>grouptest<br /> - OK<br /> - Test cases run: 10/10, Passes: 37, Failures: 0, Exceptions: 0</strong> - </div> - </p> + </p> + <p> + The results show up nicely in the console : + <div class="console"> + home: /$ php test_of_all_modules.php<br /> + <strong>grouptest<br /> + OK<br /> + Test cases run: 10/10, Passes: 37, Failures: 0, Exceptions: 0</strong> + </div> + </p> + </section> </content> <internal> <link>Introducing <a href="#autorun">'autorun'</a>.</link> Modified: simpletest/trunk/docs/source/en/experimental_dom_tester.xml =================================================================== --- simpletest/trunk/docs/source/en/experimental_dom_tester.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/experimental_dom_tester.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -2,32 +2,32 @@ <page title="Testing elements by CSS selector" here="DOM tester"> <long_title>[experimental] Testing elements by CSS selector</long_title> <content> - <div class="experimental"> - Careful : this documentation refers to un-released code. It's only available in CVS. - </div> - <p> - Before SimpleTest2 gets a new browser (PHP5 only and DOM based), a new - extension made its way to the SimpleTest trunk. - </p> - <p> - Note : it's already PHP5 only. - </p> - <p> - <a class="target" name="recorder"><h2>Testing for Web2.0</h2></a> - </p> - <p> - 1998 seems a long time ago now : it's the year - the <a href="http://www.webstandards.org/about/">the Web Standards Project (WaSP)</a> - started fighting for standards. - </p> - <p> - Nearly ten years later, every web developper is now familiar with CSS : - <em>id</em> & <em>class</em> are the new tools of the trade. - The tricks you've learned while styling, you can re-use them when testing your web site. - </p> - <p> - I was about to start with the <a href="http://flickr.com/">Flickr home page</a> - but then again, this is what the HTML source looks like : + <introduction> + <div class="experimental"> + Careful : this documentation refers to un-released code. It's only available in CVS. + </div> + <p> + Before SimpleTest2 gets a new browser (PHP5 only and DOM based), a new + extension made its way to the SimpleTest trunk. + </p> + <p> + Note : it's already PHP5 only. + </p> + </introduction> + <section name="recorder" title="Testing for Web2.0"> + <p> + 1998 seems a long time ago now : it's the year + the <a href="http://www.webstandards.org/about/">the Web Standards Project (WaSP)</a> + started fighting for standards. + </p> + <p> + Nearly ten years later, every web developper is now familiar with CSS : + <em>id</em> & <em>class</em> are the new tools of the trade. + The tricks you've learned while styling, you can re-use them when testing your web site. + </p> + <p> + I was about to start with the <a href="http://flickr.com/">Flickr home page</a> + but then again, this is what the HTML source looks like : <php><![CDATA[ <body> <div id="beacon"><img src="http://geo.yahoo.com/f?s=792600119&t=7797cfa4695ea4166ba6c8ee269ec1b6"; width="0" height="0" alt="" /></div> @@ -38,8 +38,8 @@ <td> [...] ]]></php> - Who said <cite>too many tables ?</cite> So I picked something else... - the <a href="http://simpletest.org/">SimpleTest home page</a> ! + Who said <cite>too many tables ?</cite> So I picked something else... + the <a href="http://simpletest.org/">SimpleTest home page</a> ! <php><![CDATA[ <body> <div> @@ -52,22 +52,21 @@ <a href="en/download.html"><img name="simpletestdownload" src="images/simpletest-download.png" width="305" height="109" border="0" id="simpletestdownload" alt="" /></a> [...] ]]></php> - </p> - <p> - <a class="target" name="recorder-results"><h2>Basic CSS selectors...</h2></a> - </p> - <p> - As usual we start with the necessary <code>require_once</code> + </p> + </section> + <section name="recorder-results" title="Basic CSS selectors..."> + <p> + As usual we start with the necessary <code>require_once</code> <php><![CDATA[ <?php require_once(dirname(__FILE__) . '/../../autorun.php'); require_once(dirname(__FILE__) . '/../dom_tester.php'); ?> ]]></php> - The <code>DomTestCase</code> extends the <code>WebTestCase</code>, - we can just use it the same way. - </p> - <p> + The <code>DomTestCase</code> extends the <code>WebTestCase</code>, + we can just use it the same way. + </p> + <p> <php><![CDATA[ <?php require_once(dirname(__FILE__) . '/../../autorun.php'); @@ -86,50 +85,49 @@ } ?> ]]></php> - </p> - <p> - I was expecting to get a nice green bar straight away : - I did wrote the HTML template after all. - Unfortunately it didn't happen, PHP gave me some nice exceptions : - <div class="console"> - home: /$ php dom_tester_doc_test.php<br /> - <strong>dom_tester_doc_test.php<br /> - Exception 1!<br /> - Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestlogo already defined in Entity, line: 12] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> - in testGet<br /> - in TestOfLiveCssSelectors<br /> - Exception 2!<br /> - Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestdownload already defined in Entity, line: 16] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> - in testGet<br /> - in TestOfLiveCssSelectors<br /> - Exception 3!<br /> - Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpleteststarttesting already defined in Entity, line: 24] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> - in testGet<br /> - in TestOfLiveCssSelectors<br /> - Exception 4!<br /> - Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestsupport already defined in Entity, line: 38] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> - in testGet<br /> - in TestOfLiveCssSelectors<br /> - FAILURES!!!<br /> - Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 4<br /></strong> - </div> - That's what validation is all about I guess. - </p> - <p> - Back to the drawing board... A simple fix later, everything is fine. - <div class="console"> - home: /$ php dom_tester_doc_test.php<br /> - <strong>dom_tester_doc_test.php<br /> - OK<br /> - Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 0<br /></strong> - </div> - </p> - <p> - <a class="target" name="recorder-results"><h2>...and non so basic selectors</h2></a> - </p> - <p> - If you thought it was easy, we can make things a little bit more difficult - - or precise - with attribute selectors : + </p> + <p> + I was expecting to get a nice green bar straight away : + I did wrote the HTML template after all. + Unfortunately it didn't happen, PHP gave me some nice exceptions : + <div class="console"> + home: /$ php dom_tester_doc_test.php<br /> + <strong>dom_tester_doc_test.php<br /> + Exception 1!<br /> + Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestlogo already defined in Entity, line: 12] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> + in testGet<br /> + in TestOfLiveCssSelectors<br /> + Exception 2!<br /> + Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestdownload already defined in Entity, line: 16] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> + in testGet<br /> + in TestOfLiveCssSelectors<br /> + Exception 3!<br /> + Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpleteststarttesting already defined in Entity, line: 24] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> + in testGet<br /> + in TestOfLiveCssSelectors<br /> + Exception 4!<br /> + Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestsupport already defined in Entity, line: 38] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br /> + in testGet<br /> + in TestOfLiveCssSelectors<br /> + FAILURES!!!<br /> + Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 4<br /></strong> + </div> + That's what validation is all about I guess. + </p> + <p> + Back to the drawing board... A simple fix later, everything is fine. + <div class="console"> + home: /$ php dom_tester_doc_test.php<br /> + <strong>dom_tester_doc_test.php<br /> + OK<br /> + Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 0<br /></strong> + </div> + </p> + </section> + <section name="recorder-results" title="...and non so basic selectors"> + <p> + If you thought it was easy, we can make things a little bit more difficult - + or precise - with attribute selectors : <php><![CDATA[ [...] class TestOfLiveCssSelectors extends DomTestCase { @@ -149,15 +147,15 @@ } [...] ]]></php> - <div class="console"> - home: /$ php dom_tester_doc_test.php<br /> - <strong>dom_tester_doc_test.php<br /> - OK<br /> - Test cases run: 1/1, Passes: 4, Failures: 0, Exceptions: 0<br /></strong> - </div> - </p> - <p> - Oh and by the way, combinators do work as well : + <div class="console"> + home: /$ php dom_tester_doc_test.php<br /> + <strong>dom_tester_doc_test.php<br /> + OK<br /> + Test cases run: 1/1, Passes: 4, Failures: 0, Exceptions: 0<br /></strong> + </div> + </p> + <p> + Oh and by the way, combinators do work as well : <php><![CDATA[ [...] class TestOfLiveCssSelectors extends DomTestCase { @@ -181,13 +179,14 @@ } [...] ]]></php> - <div class="console"> - home: /$ php dom_tester_doc_test.php<br /> - <strong>dom_tester_doc_test.php<br /> - OK<br /> - Test cases run: 1/1, Passes: 5, Failures: 0, Exceptions: 0<br /></strong> - </div> - </p> + <div class="console"> + home: /$ php dom_tester_doc_test.php<br /> + <strong>dom_tester_doc_test.php<br /> + OK<br /> + Test cases run: 1/1, Passes: 5, Failures: 0, Exceptions: 0<br /></strong> + </div> + </p> + </section> </content> <internal> <link>A <a href="#recorder">Recorder</a> for non-developpers.</link> Modified: simpletest/trunk/docs/source/en/experimental_intro.xml =================================================================== --- simpletest/trunk/docs/source/en/experimental_intro.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/experimental_intro.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -36,8 +36,18 @@ </external> <meta> <keywords> - php unit testing, test integration, documentation, marcus baker, simple test, - simpletest documentation, phpunit, pear, experimental, cvs, code experiment, feedback + php unit testing, + test integration, + documentation, + marcus baker, + simple test, + simpletest documentation, + phpunit, + pear, + experimental, + cvs, + code experiment, + feedback </keywords> </meta> </page> \ No newline at end of file Modified: simpletest/trunk/docs/source/en/experimental_recorder.xml =================================================================== --- simpletest/trunk/docs/source/en/experimental_recorder.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/experimental_recorder.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -2,26 +2,26 @@ <page title="Using the test results for other tools" here="Recorder"> <long_title>[experimental] Using the test results for other tools with the Recorder</long_title> <content> - <div class="experimental"> - Careful : this documentation refers to un-released code. It's only available in CVS. - </div> - <p> - What the developer wants from his tests is immediate feedback. The <em>TextReporter</em> - and the <em>HtmlReporter</em> are there to show this feedback. As quickly as possible - and as close to your working tools as possible : the console, the browser. - </p> - <p> - <a class="target" name="recorder"><h2>A Recorder for non-developpers</h2></a> - </p> - <p> - But often developers don't work alone : you may have a team contributing to - the same code base next door, a manager a little bit further away and even - a team of testers or power users on the other side of the planet. - </p> - <p> - For them as well tests' results are valuable pieces of information ! They just need - to be formatted and archived somewhere. The <em>Recorder</em> allows you to grab all - output to a simple PHP array. + <introduction> + <div class="experimental"> + Careful : this documentation refers to un-released code. It's only available in CVS. + </div> + <p> + What the developer wants from his tests is immediate feedback. The <em>TextReporter</em> + and the <em>HtmlReporter</em> are there to show this feedback. As quickly as possible + and as close to your working tools as possible : the console, the browser. + </p> + </introduction> + <section name="recorder" title="A Recorder for non-developpers"> + <p> + But often developers don't work alone : you may have a team contributing to + the same code base next door, a manager a little bit further away and even + a team of testers or power users on the other side of the planet. + </p> + <p> + For them as well tests' results are valuable pieces of information ! They just need + to be formatted and archived somewhere. The <em>Recorder</em> allows you to grab all + output to a simple PHP array. <php><![CDATA[ <?php require_once('simpletest/autorun.php');<strong> @@ -35,11 +35,11 @@ $group->run($recorder);</strong> ?> ]]></php> - </p> - <p> - Within this <em>$recorder</em> object lies the test suite information. - Let's dump the <em>$recorder->results</em> variable and check what's - in it : + </p> + <p> + Within this <em>$recorder</em> object lies the test suite information. + Let's dump the <em>$recorder->results</em> variable and check what's + in it : <php><![CDATA[ <?php array(4) { @@ -90,22 +90,21 @@ } ?> ]]></php> - </p> - <p> - <a class="target" name="recorder-results"><h2>Exploring the Recorder results</h2></a> - </p> - <p> - Each element of the <em>$recoder->results</em> array contains one assertion's - information : - <ul> - <li><em>time</em> : when the assertion was executed, in a timestamp format.</li> - <li><em>status</em> : either <strong>Passed</strong> or <strong>Failed</strong></li> - <li><em>test</em> : the name of the test</li> - <li><em>message</em> : the actual message, useful for understanding what went wrong</li> - </ul> - </p> - <p> - Now iterating throught the results becomes really easy... + </p> + </section> + <section name="recorder-results" title="Exploring the Recorder results"> + <p> + Each element of the <em>$recoder->results</em> array contains one assertion's + information : + <ul> + <li><em>time</em> : when the assertion was executed, in a timestamp format.</li> + <li><em>status</em> : either <strong>Passed</strong> or <strong>Failed</strong></li> + <li><em>test</em> : the name of the test</li> + <li><em>message</em> : the actual message, useful for understanding what went wrong</li> + </ul> + </p> + <p> + Now iterating throught the results becomes really easy... <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -125,7 +124,8 @@ </strong> ?> ]]></php> - </p> + </p> + </section> </content> <internal> <link>A <a href="#recorder">Recorder</a> for non-developpers.</link> Modified: simpletest/trunk/docs/source/en/extension_eclipse.xml =================================================================== --- simpletest/trunk/docs/source/en/extension_eclipse.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/extension_eclipse.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -3,151 +3,153 @@ <long_title>Simpletest Eclipse Plugin Documentation</long_title> <content> <section name="compat" title="Compatibility"> - <ul> - <li> - <b>Operating System.</b><br/> - This plugin should work on any platform on which Eclipse works. Specifically - the plugin has been tested to work on Linux, OS X, and Windows. If the - plugin does not appear to work on one of these platforms a new incompatibility - may have emerged, but this is relatively unlikely. - </li> - <li> - <b>Eclipse</b><br/> - The plugin has been designed to work with Eclipse versions 3.1.X+ and 3.2.X+. - Eclipse in general requires a JVM version of 1.4.x; there are no additional requirements for the plugin. - </li> - <li> - <b>PHP</b><br/> - The plugin has been tested to work with PHP 4.3.x+ (including PHP 5.1.x.). - </li> - <li> - <b>Xdebug</b><br/> - The plugin can be configured to work with Xdebug (version 2.0.0RC1 or later). - The php.ini file which is used by the plugin (see below for specifying the php.ini file) must load the Xdebug extension. - This is usually accomplished by adding a zend_extension_ts="Some Windows Path" or zend_extension="Some Linux Path" to your php.ini file. - Specific instructions can be found at: <a href="http://xdebug.org/install.php">http://xdebug.org/install.php</a> - Do not worry about specifying any other parameters, the plugin will handle setting the necessary parameters, as needed. - </li> - <li> - <b>Simpletest</b><br/> - The plugin has been designed to work with a specific version of Simpletest - and in fact includes the associated version of Simpletest in the plugin for compatibility. - A plugin with a version number of 1.0.0_0.0.4 would indicate that the plugin was compatible - with Simpletest version 1.0.0 and was version 0.0.4 of the plugin. - Some slight modifications to the Simpletest code are required to make the plugin - work with Simpletest; these modifications may or may not be in the released version of Simpletest. - </li> - <li> - <b>PHPUnit2</b><br/> - Starting with plugin version 0.1.6 experimental support for the CVS version of PHPUnit2 - is available. To use PHPUnit2 select a path to PHPUnit2 and select PHPUnit2 test instead of - SimpleTest. Note: this is the path to the folder that contains the PHPUnit2 - folder. PHPUnit3 is not currently supported but will be supported in the near future. - </li> - </ul> + <ul> + <li> + <b>Operating System.</b><br/> + This plugin should work on any platform on which Eclipse works. Specifically + the plugin has been tested to work on Linux, OS X, and Windows. If the + plugin does not appear to work on one of these platforms a new incompatibility + may have emerged, but this is relatively unlikely. + </li> + <li> + <b>Eclipse</b><br/> + The plugin has been designed to work with Eclipse versions 3.1.X+ and 3.2.X+. + Eclipse in general requires a JVM version of 1.4.x; there are no additional requirements for the plugin. + </li> + <li> + <b>PHP</b><br/> + The plugin has been tested to work with PHP 4.3.x+ (including PHP 5.1.x.). + </li> + <li> + <b>Xdebug</b><br/> + The plugin can be configured to work with Xdebug (version 2.0.0RC1 or later). + The php.ini file which is used by the plugin (see below for specifying the php.ini file) must load the Xdebug extension. + This is usually accomplished by adding a zend_extension_ts="Some Windows Path" or zend_extension="Some Linux Path" to your php.ini file. + Specific instructions can be found at: <a href="http://xdebug.org/install.php">http://xdebug.org/install.php</a> + Do not worry about specifying any other parameters, the plugin will handle setting the necessary parameters, as needed. + </li> + <li> + <b>Simpletest</b><br/> + The plugin has been designed to work with a specific version of Simpletest + and in fact includes the associated version of Simpletest in the plugin for compatibility. + A plugin with a version number of 1.0.0_0.0.4 would indicate that the plugin was compatible + with Simpletest version 1.0.0 and was version 0.0.4 of the plugin. + Some slight modifications to the Simpletest code are required to make the plugin + work with Simpletest; these modifications may or may not be in the released version of Simpletest. + </li> + <li> + <b>PHPUnit2</b><br/> + Starting with plugin version 0.1.6 experimental support for the CVS version of PHPUnit2 + is available. To use PHPUnit2 select a path to PHPUnit2 and select PHPUnit2 test instead of + SimpleTest. Note: this is the path to the folder that contains the PHPUnit2 + folder. PHPUnit3 is not currently supported but will be supported in the near future. + </li> + </ul> </section> <section name="install" title="Installation"> - <ol> - <li>Download and Install Eclipse (<a href="http://www.eclipse.org">www.eclipse.org</a>) – if you are not sure what to download, download the Eclipse 3.1.0 SDK.</li> - <li>Download the latest Simpletest Eclipse plug-in zip file (<a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=159054">Simpletest Sourceforge</a>)</li> - <li>Extract the zip file to a temporary location {this will be referred to later in this documentation as $unzip}</li> - <li>Start Eclipse</li> - <li>Open the Install Wizard by clicking "Help" > "Software Updates" > "Find and Install" from the menu bar.</li> - <li>Select the second button, "Search for new features to install" and click "Next".</li> - <li>Click the button on the right hand side, "New Local Site".</li> - <li>Select the folder $unzip {the folder extracted previously}.</li> - <li>Click the "OK" button.</li> - <li>In the "Edit Local Site" window, Click the "OK" button</li> - <li>Click the "Finish" button</li> - <li>In the "Search Results" window, drill down and select "Simpletest plug-in 0.0.x"</li> - <li>Click the "Next" button.</li> - <li>Read the license and accept the license by clicking the "I accept the terms in the license agreement" radio button and then clicking the "Next" button</li> - <li>In the "Installation" window you can choose to change the location -- most users should just click the "Finish" button</li> - <li>In the "Feature Verification" window, click the "Install" button.</li> - <li>When prompted, restart Eclipse</li> - <li> - <p>After starting Eclipse for the first time after installation - you will need to perform a quick configuration of the Simpletest Plug-in. - To perform this configuration: - </p> - <ol type="a"> - <li> - Select "Window" > "Preferences" from the menu bar - </li> - <li> - Select "Simpletest" from the categories on the left hand side of the popup box. - </li> - <li> - Enter or Browse for the location of a PHP executable to use. - </li> - <li> - Leave the include file blank - </li> - <li> - Enter .php as the Test File Suffix. - Alternately if you name your test PHP files with a sufficiently different suffix - (e.g sometest.tst.php) you could enter in a more differentiating suffix (e.g. .tst.php). - This helps when the plug-in is looking for tests to execute. - </li> - <li> - Hit the "Ok" button to close the preferences window. - </li> + <ol> + <li>Download and Install Eclipse (<a href="http://www.eclipse.org">www.eclipse.org</a>) – if you are not sure what to download, download the Eclipse 3.1.0 SDK.</li> + <li>Download the latest Simpletest Eclipse plug-in zip file (<a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=159054">Simpletest Sourceforge</a>)</li> + <li>Extract the zip file to a temporary location {this will be referred to later in this documentation as $unzip}</li> + <li>Start Eclipse</li> + <li>Open the Install Wizard by clicking "Help" > "Software Updates" > "Find and Install" from the menu bar.</li> + <li>Select the second button, "Search for new features to install" and click "Next".</li> + <li>Click the button on the right hand side, "New Local Site".</li> + <li>Select the folder $unzip {the folder extracted previously}.</li> + <li>Click the "OK" button.</li> + <li>In the "Edit Local Site" window, Click the "OK" button</li> + <li>Click the "Finish" button</li> + <li>In the "Search Results" window, drill down and select "Simpletest plug-in 0.0.x"</li> + <li>Click the "Next" button.</li> + <li>Read the license and accept the license by clicking the "I accept the terms in the license agreement" radio button and then clicking the "Next" button</li> + <li>In the "Installation" window you can choose to change the location -- most users should just click the "Finish" button</li> + <li>In the "Feature Verification" window, click the "Install" button.</li> + <li>When prompted, restart Eclipse</li> + <li> + <p>After starting Eclipse for the first time after installation + you will need to perform a quick configuration of the Simpletest Plug-in. + To perform this configuration: + </p> + <ol type="a"> + <li> + Select "Window" > "Preferences" from the menu bar + </li> + <li> + Select "Simpletest" from the categories on the left hand side of the popup box. + </li> + <li> + Enter or Browse for the location of a PHP executable to use. + </li> + <li> + Leave the include file blank + </li> + <li> + Enter .php as the Test File Suffix. + Alternately if you name your test PHP files with a sufficiently different suffix + (e.g sometest.tst.php) you could enter in a more differentiating suffix (e.g. .tst.php). + This helps when the plug-in is looking for tests to execute. + </li> + <li> + Hit the "Ok" button to close the preferences window. + </li> + </ol> + </li> </ol> - </li> - </ol> </section> <section name="update" title="Update Existing Installation"> - Note: this will only work if you have previously installed the plugin using the - Eclipse installation wizard. If you previously copied directories for installation, - it is recommended that you shutdown Eclipse, delete the previous version directories, and - follow the Installation instructions above (you should not have to perform the initial configuration - portion). - <ol> - <li>Select "Help" > "Software Updates" > "Manage Configuration" from the menu</li> - <li>Drill down to find the Simpletest plugin and select it</li> - <li>In the right hand pane click the link for "Scan for Updates"</li> - <li>IF no updates are found, navigate to Window > Preferences > Install/Update > Valid Updates in the Eclipse preferences and select 'Compatible', not 'equivalent'. Then repeat the steps above.</li> - <li>Select the feature versions that you wish to upgrade, and click "Next".</li> - <li>Review the license agreements for the upgraded features. If the terms of all these licenses are acceptable, check "I accept the terms in the license agreements." Do not proceed to download the features if the license terms are not acceptable.</li> - <li>Click "Install" to allow the downloading and installing to proceed.</li> - <li>Once all the features and plug-ins have been downloaded successfully and their files installed into the product on the local computer, a new configuration that incorporates these features and plug-ins will be formulated. Click Yes when asked to exit and restart the Workbench for the changes to take effect.</li> - </ol> + Note: this will only work if you have previously installed the plugin using the + Eclipse installation wizard. If you previously copied directories for installation, + it is recommended that you shutdown Eclipse, delete the previous version directories, and + follow the Installation instructions above (you should not have to perform the initial configuration + portion). + <ol> + <li>Select "Help" > "Software Updates" > "Manage Configuration" from the menu</li> + <li>Drill down to find the Simpletest plugin and select it</li> + <li>In the right hand pane click the link for "Scan for Updates"</li> + <li>IF no updates are found, navigate to Window > Preferences > Install/Update > Valid Updates in the Eclipse preferences and select 'Compatible', not 'equivalent'. Then repeat the steps above.</li> + <li>Select the feature versions that you wish to upgrade, and click "Next".</li> + <li>Review the license agreements for the upgraded features. If the terms of all these licenses are acceptable, check "I accept the terms in the license agreements." Do not proceed to download the features if the license terms are not acceptable.</li> + <li>Click "Install" to allow the downloading and installing to proceed.</li> + <li>Once all the features and plug-ins have been downloaded successfully and their files installed into the product on the local computer, a new configuration that incorporates these features and plug-ins will be formulated. Click Yes when asked to exit and restart the Workbench for the changes to take effect.</li> + </ol> + </section> + <section name="uninstall" title="Uninstall"> + <p> + Note: this will only work if the plugin was installed via the Feature Update method. If installed via alternate methods, then the plugin can be uninstalled by deleting the directories which were previously added. + </p> + <ol> + <li>Select "Help" > "Software Updates" > "Manage Configuration"</li> + <li>Drill down to find the Simpletest plugin</li> + <li>Right-click on the Simpletest plugin and select the option "Disable"</li> + <li>when prompted, restart Eclipse</li> + <li>After Eclipse has restarted, select "Help" > "Software Updates" > "Manage Configuration" from the menu bar</li> + <li>Select the option from the toolbar "Show Disabled Features"</li> + <li>Drill down to find the Simpletest plugin</li> + <li>Right-click on the Simpletest plugin and select the option "Uninstall"</li> + <li>When prompted, restart Eclipse</li> + </ol> </section> - <section name="uninstall" title="Uninstall"> - Note: this will only work if the plugin was installed via the Feature Update method. If installed via alternate methods, then the plugin can be uninstalled by deleting the directories which were previously added. - <ol> - <li>Select "Help" > "Software Updates" > "Manage Configuration"</li> - <li>Drill down to find the Simpletest plugin</li> - <li>Right-click on the Simpletest plugin and select the option "Disable"</li> - <li>when prompted, restart Eclipse</li> - <li>After Eclipse has restarted, select "Help" > "Software Updates" > "Manage Configuration" from the menu bar</li> - <li>Select the option from the toolbar "Show Disabled Features"</li> - <li>Drill down to find the Simpletest plugin</li> - <li>Right-click on the Simpletest plugin and select the option "Uninstall"</li> - <li>When prompted, restart Eclipse</li> - </ol> - </section> <section name="usage" title="Usage"> - <p> - The following details some sample usages of the plugin. - </p> - <ol> - <li>Create a new test project (a holding place for related files) - <ol> - <li>Select "File" > "New" > "Project.." from the menu</li> - <li>Expand the folder "General" and select "Project"</li> - <li>Click the "Next" button</li> - <li>On the next tab enter a project name: "Test"</li> - <li>Use the default Project Contents</li> - <li>Click the "Finish" button</li> - </ol> - </li> - <li>Create a Single Passing Test - <ol> - <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li> - <li>For the filename enter: test1.php and click "Finish"</li> - <li>Double-click on the test1.php entry in the Package Explorer which should open a new view to edit the file.</li> - <li>Enter the following for the contents of the file: + <p> + The following details some sample usages of the plugin. + </p> + <ol> + <li>Create a new test project (a holding place for related files) + <ol> + <li>Select "File" > "New" > "Project.." from the menu</li> + <li>Expand the folder "General" and select "Project"</li> + <li>Click the "Next" button</li> + <li>On the next tab enter a project name: "Test"</li> + <li>Use the default Project Contents</li> + <li>Click the "Finish" button</li> + </ol> + </li> + <li>Create a Single Passing Test + <ol> + <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li> + <li>For the filename enter: test1.php and click "Finish"</li> + <li>Double-click on the test1.php entry in the Package Explorer which should open a new view to edit the file.</li> + <li>Enter the following for the contents of the file: <php><![CDATA[ <?php class test1 extends UnitTestCase { @@ -160,18 +162,18 @@ } ?> ]]></php> + </li> + <li>Select "File" > "Save" from the menu.</li> + <li>Right click on the test1.php entry and select "Run" > "Run Simpletest".</li> + <li>The "Result View" should populate with information about the test run and the Simpletest console should fill with some information as well.</li> + </ol> </li> - <li>Select "File" > "Save" from the menu.</li> - <li>Right click on the test1.php entry and select "Run" > "Run Simpletest".</li> - <li>The "Result View" should populate with information about the test run and the Simpletest console should fill with some information as well.</li> - </ol> - </li> - <li>Single Test class multiple tests - <ol> - <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li> - <li>For the filename enter: test2.php and click "Finish".</li> - <li>Double-click on the test2.php entry in the Package Explorer which should open a new view to edit the file.</li> - <li>Enter the following for the contents of the file: + <li>Single Test class multiple tests + <ol> + <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li> + <li>For the filename enter: test2.php and click "Finish".</li> + <li>Double-click on the test2.php entry in the Package Explorer which should open a new view to edit the file.</li> + <li>Enter the following for the contents of the file: <php><![CDATA[ <?php class test2 extends UnitTestCase { @@ -190,18 +192,18 @@ } ?> ]]></php> + </li> + <li>Select "File" > "save" from the menu bar.</li> + <li>Right click on the test2.php entry and select "Run" > "Run Simpletest".</li> + <li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li> + </ol> </li> - <li>Select "File" > "save" from the menu bar.</li> - <li>Right click on the test2.php entry and select "Run" > "Run Simpletest".</li> - <li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li> - </ol> - </li> - <li>Group Tests (test multiple files at once) - <ol> - <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File"</li> - <li>For the filename enter: grouptest.php and click "Finish".</li> - <li>Double-click on the grouptest.php entry in the Package Explorer which should open a new view to edit the file.</li> - <li>Enter the following for the contents of the file: + <li>Group Tests (test multiple files at once) + <ol> + <li>In the Package Explorer View right-click on the "Test" project and select "New" > "File"</li> + <li>For the filename enter: grouptest.php and click "Finish".</li> + <li>Double-click on the grouptest.php entry in the Package Explorer which should open a new view to edit the file.</li> + <li>Enter the following for the contents of the file: <php><![CDATA[ <?php class myGroupTest extends GroupTest { @@ -213,41 +215,41 @@ } ?> ]]></php> + </li> + <li>Select "File" > "save" from the menu</li> + <li>Right click on the grouptest.php entry and select "Run" > "Run Simpletest"</li> + <li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li> + </ol> </li> - <li>Select "File" > "save" from the menu</li> - <li>Right click on the grouptest.php entry and select "Run" > "Run Simpletest"</li> - <li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li> </ol> - </li> - </ol> </section> <section name="known" title="Known Issues"> - <ul> - <li> - Make sure that if a constructor is used in the test case - that the last line of the constructor calls the parent - constructor (e.g. parent::UnitTestCase) - </li> - <li> - Do not put any assertions into the test class constructor - </li> - <li> - If you get an error indicating that a class could not load; then restart Eclipse. Once - Eclipse restarts, open the Result View manually by selecting "Window"->"Show View"->"Other..." - Then select the SimpleTest Category and select "Result View" and click "OK". - </li> - </ul> + <ul> + <li> + Make sure that if a constructor is used in the test case + that the last line of the constructor calls the parent + constructor (e.g. parent::UnitTestCase) + </li> + <li> + Do not put any assertions into the test class constructor + </li> + <li> + If you get an error indicating that a class could not load; then restart Eclipse. Once + Eclipse restarts, open the Result View manually by selecting "Window"->"Show View"->"Other..." + Then select the SimpleTest Category and select "Result View" and click "OK". + </li> + </ul> </section> <section name="todo" title="Future Features"> - <p>These are features that should eventually make it into this plugin</p> - <ul> - <li> - Allow different "include" file on each runner (override the "master" include) - </li> - <li> - Handle fatal errors better - </li> - </ul> + <p>These are features that should eventually make it into this plugin</p> + <ul> + <li> + Allow different "include" file on each runner (override the "master" include) + </li> + <li> + Handle fatal errors better + </li> + </ul> </section> </content> Modified: simpletest/trunk/docs/source/en/first_test_tutorial.xml =================================================================== --- simpletest/trunk/docs/source/en/first_test_tutorial.xml 2008-02-16 17:52:11 UTC (rev 1657) +++ simpletest/trunk/docs/source/en/first_test_tutorial.xml 2008-02-18 11:14:26 UTC (rev 1658) @@ -2,288 +2,272 @@ @@ Diff output truncated at 100000 characters. @@ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Travis Snoozy <ai2097@us...> - 2008-02-18 08:08:41
|
Hey folks, I forgot I had this patch applied locally; it adds referer support for the simulated browser. This is really helpful for me when running tests against old versions of WordPress (which relied on the referer string being correct for certain operations). I haven't put a lot of thought into how to unit test it, and no tests are included with this patch (sorry). Enjoy, -- Travis In Series maintainer Random coder & quality guy <http://remstate.com/> |
From: <pp11@us...> - 2008-02-16 17:52:14
|
Revision: 1657 http://simpletest.svn.sourceforge.net/simpletest/?rev=1657&view=rev Author: pp11 Date: 2008-02-16 09:52:11 -0800 (Sat, 16 Feb 2008) Log Message: ----------- First go at the rewriting of the docs using "autorun" Modified Paths: -------------- simpletest/trunk/docs/source/en/overview.xml simpletest/trunk/docs/source/en/partial_mocks_documentation.xml simpletest/trunk/docs/source/en/simple_test.xml simpletest/trunk/docs/source/en/unit_test_documentation.xml Modified: simpletest/trunk/docs/source/en/overview.xml =================================================================== --- simpletest/trunk/docs/source/en/overview.xml 2008-02-16 15:13:53 UTC (rev 1656) +++ simpletest/trunk/docs/source/en/overview.xml 2008-02-16 17:52:11 UTC (rev 1657) @@ -23,6 +23,8 @@ A <a local="unit_test_documentation">test case</a> looks like this... <php><![CDATA[ <?php +require_once('simpletest/autorun.php'); + class <strong>MyTestCase</strong> extends UnitTestCase { <strong> function testLogWroteMessage() { @@ -71,6 +73,9 @@ A <a local="web_tester_documentation">WebTestCase</a> looks like this... <php><![CDATA[ <?php +require_once('simpletest/autorun.php'); +require_once('simpletest/web_tester.php'); + class <strong>MySiteTest</strong> extends WebTestCase { <strong> function testHomePage() { Modified: simpletest/trunk/docs/source/en/partial_mocks_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/partial_mocks_documentation.xml 2008-02-16 15:13:53 UTC (rev 1656) +++ simpletest/trunk/docs/source/en/partial_mocks_documentation.xml 2008-02-16 17:52:11 UTC (rev 1657) @@ -7,7 +7,7 @@ A partial mock is simply a pattern to alleviate a specific problem in testing with mock objects, that of getting mock objects into tight corners. - It's quite a limited tool and possibly not even a good idea. + It's quite a limited tool and possibly not even a good idea. It is included with SimpleTest because I have found it useful on more than one occasion and has saved a lot of work at that point. </p> @@ -20,7 +20,7 @@ creator is the one you want to test. This means that the created object should be mocked, but we can hardly tell our class under test to create a mock instead. - The tested class doesn't even know it is running inside a test + The tested class doesn't even know it is running inside a test after all. </p> <p> @@ -29,16 +29,16 @@ The connection method might look something like... <php><![CDATA[ <strong><?php - require_once('socket.php'); +require_once('socket.php'); - class Telnet { +class Telnet { + ... + function &connect($ip, $port, $username, $password) { + $socket = &new Socket($ip, $port); + $socket->read( ... ); ... - function &connect($ip, $port, $username, $password) { - $socket = &new Socket($ip, $port); - $socket->read( ... ); - ... - } } +} ?></strong> ]]></php> We would really like to have a mock object version of the socket @@ -58,15 +58,15 @@ Here this would be... <php><![CDATA[ <?php - require_once('socket.php'); +require_once('socket.php'); - class Telnet { +class Telnet { + ... + <strong>function &connect(&$socket, $username, $password) { + $socket->read( ... ); ... - <strong>function &connect(&$socket, $username, $password) { - $socket->read( ... ); - ... - }</strong> - } + }</strong> +} ?> ]]></php> This means that the test code is typical for a test involving @@ -87,26 +87,26 @@ You would hardly want your top level application creating every low level file, socket and database connection ever needed. - It wouldn't know the constructor parameters anyway. + It wouldn't know the constructor parameters anyway. </p> <p> The next simplest compromise is to have the created object passed in as an optional parameter... <php><![CDATA[ <?php - require_once('socket.php'); +require_once('socket.php'); - class Telnet { - ...<strong> - function &connect($ip, $port, $username, $password, $socket = false) { - if (!$socket) { - $socket = &new Socket($ip, $port); - } - $socket->read( ... );</strong> - ... - return $socket; +class Telnet { + ...<strong> + function &connect($ip, $port, $username, $password, $socket = false) { + if (!$socket) { + $socket = &new Socket($ip, $port); } + $socket->read( ... );</strong> + ... + return $socket; } +} ?> ]]></php> For a quick solution this is usually good enough. @@ -134,20 +134,20 @@ The next method is to pass in a factory object to do the creation... <php><![CDATA[ <?php - require_once('socket.php'); +require_once('socket.php'); - class Telnet {<strong> - function Telnet(&$network) { - $this->_network = &$network; - }</strong> +class Telnet {<strong> + function Telnet(&$network) { + $this->_network = &$network; + }</strong> + ... + function &connect($ip, $port, $username, $password) {<strong> + $socket = &$this->_network->createSocket($ip, $port); + $socket->read( ... );</strong> ... - function &connect($ip, $port, $username, $password) {<strong> - $socket = &$this->_network->createSocket($ip, $port); - $socket->read( ... );</strong> - ... - return $socket; - } + return $socket; } +} ?> ]]></php> This is probably the most highly factored answer as creation @@ -186,20 +186,20 @@ Firstly we move the socket creation into its own method... <php><![CDATA[ <?php - require_once('socket.php'); +require_once('socket.php'); - class Telnet { +class Telnet { + ... + function &connect($ip, $port, $username, $password) {<strong> + $socket = &$this->_createSocket($ip, $port);</strong> + $socket->read( ... ); ... - function &connect($ip, $port, $username, $password) {<strong> - $socket = &$this->_createSocket($ip, $port);</strong> - $socket->read( ... ); - ... - }<strong> + }<strong> - function &_createSocket($ip, $port) { - return new Socket($ip, $port); - }</strong> - } + function &_createSocket($ip, $port) { + return new Socket($ip, $port); + }</strong> +} ?> ]]></php> This is the only change we make to the application code. @@ -332,7 +332,7 @@ </section> <section name="less" title="Testing less than a class"> <p> - The mocked out methods don't have to be factory methods, + The mocked out methods don't have to be factory methods, they could be any sort of method. In this way partial mocks allow us to take control of any part of a class except the constructor. @@ -340,7 +340,7 @@ except one we actually want to test. </p> <p> - This last situation is all rather hypothetical, as I haven't + This last situation is all rather hypothetical, as I haven't tried it. I am open to the possibility, but a little worried that forcing object granularity may be better for the code quality. @@ -348,7 +348,7 @@ or for occasional testing of the TemplateMethod pattern. </p> <p> - It's all going to come down to the coding standards of your + It's all going to come down to the coding standards of your project to decide which mechanism you use. </p> </section> Modified: simpletest/trunk/docs/source/en/simple_test.xml =================================================================== --- simpletest/trunk/docs/source/en/simple_test.xml 2008-02-16 15:13:53 UTC (rev 1656) +++ simpletest/trunk/docs/source/en/simple_test.xml 2008-02-16 17:52:11 UTC (rev 1657) @@ -34,7 +34,7 @@ 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 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> @@ -54,8 +54,7 @@ <em>tests/log_test.php</em> and populate it as follows... <php><![CDATA[ <?php<strong> -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); +require_once('simpletest/autorun.php'); require_once('../classes/log.php'); class TestOfLogging extends UnitTestCase { @@ -65,19 +64,18 @@ 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. - The <code>TestOfLogging</code> is our frst test case and it's + The <code>TestOfLogging</code> is our frst test case and it's currently empty. </p> <p> 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 <code>Log</code> class + We'll assume that the <code>Log</code> class takes the file name to write to in the constructor and we have a temporary folder in which to place this file... <php><![CDATA[ <?php -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); +require_once('simpletest/autorun.php'); require_once('../classes/log.php'); class TestOfLogging extends UnitTestCase { @@ -105,29 +103,8 @@ </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... -<php><![CDATA[ -<?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> -?> -]]></php> + No other code is necessary : we can just open the page + with our browser. </p> <p> On failure the display looks like this... @@ -155,10 +132,10 @@ function Log($file_path) { } - function message() { - } + function message() { + } } -?>; +?> ]]></php> </p> </section> @@ -170,37 +147,21 @@ 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... + Our first step is to create a new file called <em>tests/all_tests.php</em> + and insert the following code... <php><![CDATA[ -<?php<strong> -require_once('../classes/log.php');</strong> +<strong><?php +require_once('simpletest/autorun.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> +class AllTests extends TestSuite { + function AllTests() { + $this->TestSuite('All tests'); + $this->addFile('log_test.php'); } } ?></strong> ]]></php> - Next we create a new file called <em>tests/all_tests.php</em> - and insert the following code... -<php><![CDATA[ -<strong><?php -require_once('simpletest/unit_tester.php'); -require_once('simpletest/reporter.php'); - -$test = &new TestSuite('All tests'); -$test->addTestFile('log_test.php'); -$test->run(new HtmlReporter()); -?></strong> -]]></php> - The method <code>TestSuite::addTestFile()</code> + The method <code>TestSuite::addFile()</code> will include the test case file and read any new classes created that are descended from <code>SimpleTestCase</code>, of which <code>UnitTestCase</code> is one example. @@ -219,7 +180,7 @@ 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 <code>TestSuite::addTestFile()</code> + already loaded by PHP the <code>TestSuite::addFile()</code> method will not detect them. </p> <p> @@ -229,7 +190,7 @@ </section> <section name="mock" title="Using mock objects"> <p> - Let's move further into the future. + Let's move further into the future. </p> <p> Assume that our logging class is tested and completed. @@ -255,6 +216,7 @@ A conventional test case might look like this... <php><![CDATA[<strong> <?php +require_once('simpletest/autorun.php'); require_once('../classes/log.php'); require_once('../classes/session_pool.php'); @@ -283,7 +245,7 @@ not part of our test. Worse, we have created close ties with the <code>Log</code> class and this test. - What if we don't use files any more, but use ths + 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? @@ -298,7 +260,7 @@ 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 + 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> @@ -307,10 +269,12 @@ Luckily we can create such an object easily... <php><![CDATA[ <?php +require_once('simpletest/autorun.php'); require_once('../classes/log.php'); -require_once('../classes/session_pool.php');<strong> -Mock::generate('Log');</strong> +require_once('../classes/session_pool.php'); +<strong>Mock::generate('Log');</strong> + class TestOfSessionLogging extends UnitTestCase { function testLogInIsLogged() {<strong> @@ -344,10 +308,6 @@ 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> </section> <section name="web" title="Web page testing"> <p> @@ -366,11 +326,11 @@ page is fetched, from which we navigate to an "about" page and then test some client determined content. <php><![CDATA[ -<?php<strong> -require_once('simpletest/web_tester.php');</strong> -require_once('simpletest/reporter.php'); -<strong> -class TestOfAbout extends WebTestCase { +<?php +require_once('simpletest/autorun.php'); +<strong>require_once('simpletest/web_tester.php'); + +class TestOfAbout extends WebTestCase</strong> { function setUp() { $this->get('http://test-server/index.php';); @@ -382,8 +342,6 @@ $this->assertPattern('/a popular keyphrase/i'); } }</strong> -$test = &new TestOfAbout(); -$test->run(new HtmlReporter()); ?> ]]></php> With this code as an acceptance test you can ensure that @@ -419,7 +377,7 @@ from <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>. </link> <link> - The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a> + The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a> gives full detail on the classes and assertions available. </link> </external> Modified: simpletest/trunk/docs/source/en/unit_test_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/unit_test_documentation.xml 2008-02-16 15:13:53 UTC (rev 1656) +++ simpletest/trunk/docs/source/en/unit_test_documentation.xml 2008-02-16 17:52:11 UTC (rev 1657) @@ -20,6 +20,7 @@ <p> For example... <php><![CDATA[ +require_once('simpletest/autorun.php'); require_once('../classes/writer.php'); class FileTestCase extends UnitTestCase { @@ -176,7 +177,7 @@ Of course additional test methods can be added to create specific types of test case, so as to extend framework... <php><![CDATA[ -require_once('simpletest/unit_tester.php'); +require_once('simpletest/autorun.php'); <strong> class FileTester extends UnitTestCase { function FileTester($name = false) { @@ -197,6 +198,11 @@ <p> To prevent this test case being run accidently, it is advisable to mark it as <code>abstract</code>. + </p> + <p> + Alternatively you could add a + <code>SimpleTestOptions::ignore('FileTester');</code> + directive in your code. </p> <p> This new case can be now be inherited just like @@ -229,30 +235,31 @@ It is found in <em>simple_test.php</em> rather than <em>unit_tester.php</em>. See <a local="group_test_documentation">later</a> if you - want to incorporate other unit tester's + want to incorporate other unit tester's test cases in your test suites. </p> </section> <section name="running_unit" title="Running a single test case"> <p> - You won't often run single test cases except when bashing - away at a module that is having difficulty, and you don't + You won't often run single test cases except when bashing + away at a module that is having difficulty, and you don't want to upset the main test suite. - Here is the scaffolding needed to run a lone test case... + With <em>autorun</em> no particular scaffolding is needed, + just launch your particular test file and you're ready to go. + </p> + <p> + You can even decide which reporter (for example, + <code>TextReporter</code> or <code>HtmlReporter</code>) + you prefer for a specific file when launched on its own... <php><![CDATA[ <?php - require_once('simpletest/unit_tester.php');<strong> - require_once('simpletest/reporter.php');</strong> - require_once('../classes/writer.php'); +require_once('simpletest/autorun.php');<strong> +SimpleTest :: prefer(new TextReporter());</strong> +require_once('../classes/writer.php'); - class FileTestCase extends UnitTestCase { - function FileTestCase() { - $this->UnitTestCase('File test'); - } - }<strong> - - $test = &new FileTestCase(); - $test->run(new HtmlReporter());</strong> +class FileTestCase extends UnitTestCase { + ... +} ?> ]]></php> This script will run as is, but of course will output zero passes This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: SourceForge.net <noreply@so...> - 2008-02-16 15:18:36
|
Patches item #1892029, was opened at 2008-02-12 16:47 Message generated for change (Comment added) made by pp11 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1892029&group_id=76550 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Closed >Resolution: Fixed Priority: 5 Private: No Submitted By: David Heath (dgheath) Assigned to: Perrick Penet (pp11) Summary: Update FormTesting tutorial page for hidden fields Initial Comment: A proposed documentation update to explain explicitly how to test forms which rely on javascript to set a hidden form field. ---------------------------------------------------------------------- >Comment By: Perrick Penet (pp11) Date: 2008-02-16 16:18 Message: Logged In: YES user_id=292377 Originator: NO The patch was applied to the documentation source. And translated to french as well ! Thanks again for the submission. Yours, Perrick ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=547457&aid=1892029&group_id=76550 |
From: <pp11@us...> - 2008-02-16 15:13:58
|
Revision: 1656 http://simpletest.svn.sourceforge.net/simpletest/?rev=1656&view=rev Author: pp11 Date: 2008-02-16 07:13:53 -0800 (Sat, 16 Feb 2008) Log Message: ----------- Applying and translating patch [ 1892029 ] "Update FormTesting tutorial page for hidden fields" submitted by David Heath - dgheath Modified Paths: -------------- simpletest/trunk/docs/source/en/form_testing_documentation.xml simpletest/trunk/docs/source/fr/form_testing_documentation.xml Modified: simpletest/trunk/docs/source/en/form_testing_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/form_testing_documentation.xml 2008-02-14 08:58:33 UTC (rev 1655) +++ simpletest/trunk/docs/source/en/form_testing_documentation.xml 2008-02-16 15:13:53 UTC (rev 1656) @@ -123,11 +123,19 @@ <li>Images.</li> </ul> </p> - <p> - Although most standard HTML widgets are catered for by <em>SimpleTest</em>'s - built in parser, it is unlikely that JavaScript will be implemented - anytime soon. - </p> + <p> + The browser emulation offered by SimpleTest mimics + the actions which can be perform by a user on a + standard HTML page. Javascript is not supported, and + it's unlikely that support will be added any time + soon. + </p> + <p> + Of particular note is that the Javascript idiom of + passing form results by setting a hidden field cannot + be performed using the normal SimpleTest + commands. See below for a way to test such forms. + </p> </section> <section name="multiple" title="Fields with multiple values"> <p> @@ -185,10 +193,43 @@ We can then write other test code to confirm the effect of this, perhaps by logging in as that user and attempting an update. </p> + </section> + <section name="hidden-field" title="Forms which use javascript to set a hidden field"> + <p> + If you want to test a form which relies on javascript to set a hidden + field, you can't just call setField(). + The following code will <em>not</em> work: +<php><![CDATA[ +class SimpleFormTests extends WebTestCase { + function testMyJavascriptForm() { + <strong>// This does *not* work</strong> + $this->setField('a_hidden_field', '123'); + $this->clickSubmit('OK'); + } +} +]]></php> + Instead, you need to pass the additional form parameters to the + clickSubmit() method: +<php><![CDATA[ +class SimpleFormTests extends WebTestCase { + function testMyJavascriptForm() { + // Pass the hidden field value as an additional POST variable + <strong>$this->clickSubmit('OK', array('a_hidden_field'=>'123'));</strong> + } + +} +]]></php> + </p> + <p> + Bear in mind that in doing this you're effectively stubbing out a + part of your software (the javascript code in the form), and + perhaps you might be better off using something like + <a href="http://selenium.openqa.org/">Selenium</a> to ensure a complete + acceptance test. + </p> + </section> + <section name="raw" title="Raw posting"> <p> - <a class="target" name="raw"><h2>Raw posting</h2></a> - </p> - <p> If you want to test a form handler, but have not yet written or do not have access to the form itself, you can create a form submission by hand. @@ -218,6 +259,9 @@ by setting lists. </link> <link> + Bypassing javascript to <a href="#hidden-field">set a hidden field</a>. + </link> + <link> <a href="#raw">Raw posting</a> when you don't have a button to click. </link> Modified: simpletest/trunk/docs/source/fr/form_testing_documentation.xml =================================================================== --- simpletest/trunk/docs/source/fr/form_testing_documentation.xml 2008-02-14 08:58:33 UTC (rev 1655) +++ simpletest/trunk/docs/source/fr/form_testing_documentation.xml 2008-02-16 15:13:53 UTC (rev 1656) @@ -94,9 +94,18 @@ <li>Images.</li> </ul> </p> - <p> - Bien que la plupart des objets HTML standards soient couvert par le parseur de <em>SimpleTest</em>, il est peu probable que JavaScript soit impl\xE9ment\xE9 dans un futur proche. - </p> + <p> + Le navigateur propos\xE9 par SimpleTest \xE9mule les actions + qui peuvent \xEAtre r\xE9alis\xE9es par un utilisateur sur + une page HTML standard. Javascript n'est pas support\xE9 et + il y a peu de chance pour qu'il le soit prochainement. + </p> + <p> + Une attention particuli\xE8re doit \xEAtre port\xE9 aux techniques Javascript + qui changent la valeur d'un champ cach\xE9 : elles ne peuvent pas \xEAtre + r\xE9alis\xE9es avec les commandes classiques de SimpleTest. + Une m\xE9thode alternative est propos\xE9e plus loin. + </p> </section> <section name="multiple" title="Champs \xE0 valeurs multiples"> <p> @@ -144,10 +153,45 @@ ]]></php> Plut\xF4t que d'initier le champ \xE0 une valeur unique, nous lui donnons une liste de valeurs. Nous faisons la m\xEAme chose pour tester les valeurs attendues. Nous pouvons \xE9crire d'autres bouts de code de test pour confirmer cet effet, peut-\xEAtre en nous connectant comme utilisateur et en essayant d'effectuer une mise \xE0 jour. </p> + </section> + <section name="hidden-field" title="Formulaires utilisant Javascript pour changer un champ cach\xE9"> + <p> + Si vous souhaitez tester un formulaire d\xE9pendant de Javascript + pour la modification d'un champ cach\xE9, vous ne pouvez pas + simplement utiliser setField(). + Le code suivant <em>ne fonctionnera pas</em> : +<php><![CDATA[ +class SimpleFormTests extends WebTestCase { + function testMyJavascriptForm() { + <strong>// Ne fonctionne *pas*</strong> + $this->setField('un_champ_cach\xE9', '123'); + $this->clickSubmit('OK'); + } +} +]]></php> + A la place, vous aurez besoin d'ajouter le param\xE8tre suppl\xE9mentaire + du formulaire \xE0 la m\xE9thode clickSubmit() : +<php><![CDATA[ +class SimpleFormTests extends WebTestCase { + function testMyJavascriptForm() { + // Ajoute le champ cach\xE9 comme variable POST suppl\xE9mentaire + <strong>$this->clickSubmit('OK', array('un_champ_cach\xE9'=>'123'));</strong> + } + +} +]]></php> + </p> + <p> + N'oubliez pas que de la sorte, vous \xEAtes effectivement en train + de court-circuitez une partie de votre application (le code Javascript + dans le formulaire) et que peut-\xEAtre serait-il plus prudent + d'utiliser un outil comme + <a href="http://selenium.openqa.org/">Selenium</a> pour mettre sur pied + un test de recette complet. + </p> + </section> + <section name="brut" title="Envoi brut"> <p> - <a class="target" name="brut"><h2>Envoi brut</h2></a> - </p> - <p> Si vous souhaitez tester un gestionnaire de formulaire mais que vous ne l'avez pas \xE9crit ou que vous n'y avez pas encore acc\xE8s, vous pouvez cr\xE9er un envoi de formulaire \xE0 la main. <php><![CDATA[ class SimpleFormTests extends WebTestCase { @@ -160,17 +204,24 @@ }</strong> } ]]></php> - En ajoutant des donn\xE9es \xE0 la m\xE9thode <code>WebTestCase::post()</code>, nous essayons de t\xE9l\xE9charger la page via la transmission d'un formulaire. + En ajoutant des donn\xE9es \xE0 la m\xE9thode <code>WebTestCase::post()</code>, + nous essayons de t\xE9l\xE9charger la page via la transmission d'un formulaire. </p> </section> </content> <internal> <link> - Modifier les valeurs d'un formulaire et <a href="#submit">r\xE9ussir \xE0 transmettre un simple formulaire</a> + Modifier les valeurs d'un formulaire et + <a href="#submit">r\xE9ussir \xE0 transmettre un simple formulaire</a> </link> <link> - G\xE9rer des <a href="#multiple">objets \xE0 valeurs multiples</a> en initialisant des listes. + G\xE9rer des <a href="#multiple">objets \xE0 valeurs multiples</a> + en initialisant des listes. </link> + <link> + Le cas des formulaires utilisant Javascript pour + modifier <a href="#hidden-field">un champ cach\xE9</a> + </link> <link> <a href="#brut">Envoi brut</a> quand il n'existe pas de bouton \xE0 cliquer. </link> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |