simpletest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. /**
  3. * Global state for SimpleTest and kicker script in future versions.
  4. * @package SimpleTest
  5. * @subpackage UnitTester
  6. * @version $Id: simpletest.php 1723 2008-04-08 00:34:10Z lastcraft $
  7. */
  8. /**#@+
  9. * include SimpleTest files
  10. */
  11. if (version_compare(phpversion(), '5') >= 0) {
  12. require_once(dirname(__FILE__) . '/reflection_php5.php');
  13. } else {
  14. require_once(dirname(__FILE__) . '/reflection_php4.php');
  15. }
  16. require_once(dirname(__FILE__) . '/default_reporter.php');
  17. require_once(dirname(__FILE__) . '/compatibility.php');
  18. /**#@-*/
  19. /**
  20. * Registry and test context. Includes a few
  21. * global options that I'm slowly getting rid of.
  22. * @package SimpleTest
  23. * @subpackage UnitTester
  24. */
  25. class SimpleTest {
  26. /**
  27. * Reads the SimpleTest version from the release file.
  28. * @return string Version string.
  29. * @static
  30. * @access public
  31. */
  32. function getVersion() {
  33. $content = file(dirname(__FILE__) . '/VERSION');
  34. return trim($content[0]);
  35. }
  36. /**
  37. * Sets the name of a test case to ignore, usually
  38. * because the class is an abstract case that should
  39. * not be run. Once PHP4 is dropped this will disappear
  40. * as a public method and "abstract" will rule.
  41. * @param string $class Add a class to ignore.
  42. * @static
  43. * @access public
  44. */
  45. function ignore($class) {
  46. $registry = &SimpleTest::_getRegistry();
  47. $registry['IgnoreList'][strtolower($class)] = true;
  48. }
  49. /**
  50. * Scans the now complete ignore list, and adds
  51. * all parent classes to the list. If a class
  52. * is not a runnable test case, then it's parents
  53. * wouldn't be either. This is syntactic sugar
  54. * to cut down on ommissions of ignore()'s or
  55. * missing abstract declarations. This cannot
  56. * be done whilst loading classes wiithout forcing
  57. * a particular order on the class declarations and
  58. * the ignore() calls. It's just nice to have the ignore()
  59. * calls at the top of the file before the actual declarations.
  60. * @param array $classes Class names of interest.
  61. * @static
  62. * @access public
  63. */
  64. function ignoreParentsIfIgnored($classes) {
  65. $registry = &SimpleTest::_getRegistry();
  66. foreach ($classes as $class) {
  67. if (SimpleTest::isIgnored($class)) {
  68. $reflection = new SimpleReflection($class);
  69. if ($parent = $reflection->getParent()) {
  70. SimpleTest::ignore($parent);
  71. }
  72. }
  73. }
  74. }
  75. /**
  76. * Puts the object to the global pool of 'preferred' objects
  77. * which can be retrieved with SimpleTest :: preferred() method.
  78. * Instances of the same class are overwritten.
  79. * @param object $object Preferred object
  80. * @static
  81. * @access public
  82. * @see preferred()
  83. */
  84. function prefer(&$object) {
  85. $registry = &SimpleTest::_getRegistry();
  86. $registry['Preferred'][] = &$object;
  87. }
  88. /**
  89. * Retrieves 'preferred' objects from global pool. Class filter
  90. * can be applied in order to retrieve the object of the specific
  91. * class
  92. * @param array|string $classes Allowed classes or interfaces.
  93. * @static
  94. * @access public
  95. * @return array|object|null
  96. * @see prefer()
  97. */
  98. function &preferred($classes) {
  99. if (! is_array($classes)) {
  100. $classes = array($classes);
  101. }
  102. $registry = &SimpleTest::_getRegistry();
  103. for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) {
  104. foreach ($classes as $class) {
  105. if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) {
  106. return $registry['Preferred'][$i];
  107. }
  108. }
  109. }
  110. return null;
  111. }
  112. /**
  113. * Test to see if a test case is in the ignore
  114. * list. Quite obviously the ignore list should
  115. * be a separate object and will be one day.
  116. * This method is internal to SimpleTest. Don't
  117. * use it.
  118. * @param string $class Class name to test.
  119. * @return boolean True if should not be run.
  120. * @access public
  121. * @static
  122. */
  123. function isIgnored($class) {
  124. $registry = &SimpleTest::_getRegistry();
  125. return isset($registry['IgnoreList'][strtolower($class)]);
  126. }
  127. /**
  128. * @deprecated
  129. */
  130. function setMockBaseClass($mock_base) {
  131. $registry = &SimpleTest::_getRegistry();
  132. $registry['MockBaseClass'] = $mock_base;
  133. }
  134. /**
  135. * @deprecated
  136. */
  137. function getMockBaseClass() {
  138. $registry = &SimpleTest::_getRegistry();
  139. return $registry['MockBaseClass'];
  140. }
  141. /**
  142. * Sets proxy to use on all requests for when
  143. * testing from behind a firewall. Set host
  144. * to false to disable. This will take effect
  145. * if there are no other proxy settings.
  146. * @param string $proxy Proxy host as URL.
  147. * @param string $username Proxy username for authentication.
  148. * @param string $password Proxy password for authentication.
  149. * @access public
  150. */
  151. function useProxy($proxy, $username = false, $password = false) {
  152. $registry = &SimpleTest::_getRegistry();
  153. $registry['DefaultProxy'] = $proxy;
  154. $registry['DefaultProxyUsername'] = $username;
  155. $registry['DefaultProxyPassword'] = $password;
  156. }
  157. /**
  158. * Accessor for default proxy host.
  159. * @return string Proxy URL.
  160. * @access public
  161. */
  162. function getDefaultProxy() {
  163. $registry = &SimpleTest::_getRegistry();
  164. return $registry['DefaultProxy'];
  165. }
  166. /**
  167. * Accessor for default proxy username.
  168. * @return string Proxy username for authentication.
  169. * @access public
  170. */
  171. function getDefaultProxyUsername() {
  172. $registry = &SimpleTest::_getRegistry();
  173. return $registry['DefaultProxyUsername'];
  174. }
  175. /**
  176. * Accessor for default proxy password.
  177. * @return string Proxy password for authentication.
  178. * @access public
  179. */
  180. function getDefaultProxyPassword() {
  181. $registry = &SimpleTest::_getRegistry();
  182. return $registry['DefaultProxyPassword'];
  183. }
  184. /**
  185. * Accessor for global registry of options.
  186. * @return hash All stored values.
  187. * @access private
  188. * @static
  189. */
  190. function &_getRegistry() {
  191. static $registry = false;
  192. if (! $registry) {
  193. $registry = SimpleTest::_getDefaults();
  194. }
  195. return $registry;
  196. }
  197. /**
  198. * Accessor for the context of the current
  199. * test run.
  200. * @return SimpleTestContext Current test run.
  201. * @access public
  202. * @static
  203. */
  204. function &getContext() {
  205. static $context = false;
  206. if (! $context) {
  207. $context = new SimpleTestContext();
  208. }
  209. return $context;
  210. }
  211. /**
  212. * Constant default values.
  213. * @return hash All registry defaults.
  214. * @access private
  215. * @static
  216. */
  217. function _getDefaults() {
  218. return array(
  219. 'StubBaseClass' => 'SimpleStub',
  220. 'MockBaseClass' => 'SimpleMock',
  221. 'IgnoreList' => array(),
  222. 'DefaultProxy' => false,
  223. 'DefaultProxyUsername' => false,
  224. 'DefaultProxyPassword' => false,
  225. 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter()));
  226. }
  227. }
  228. /**
  229. * Container for all components for a specific
  230. * test run. Makes things like error queues
  231. * available to PHP event handlers, and also
  232. * gets around some nasty reference issues in
  233. * the mocks.
  234. * @package SimpleTest
  235. */
  236. class SimpleTestContext {
  237. var $_test;
  238. var $_reporter;
  239. var $_resources;
  240. /**
  241. * Clears down the current context.
  242. * @access public
  243. */
  244. function clear() {
  245. $this->_resources = array();
  246. }
  247. /**
  248. * Sets the current test case instance. This
  249. * global instance can be used by the mock objects
  250. * to send message to the test cases.
  251. * @param SimpleTestCase $test Test case to register.
  252. * @access public
  253. */
  254. function setTest(&$test) {
  255. $this->clear();
  256. $this->_test = &$test;
  257. }
  258. /**
  259. * Accessor for currently running test case.
  260. * @return SimpleTestCase Current test.
  261. * @access public
  262. */
  263. function &getTest() {
  264. return $this->_test;
  265. }
  266. /**
  267. * Sets the current reporter. This
  268. * global instance can be used by the mock objects
  269. * to send messages.
  270. * @param SimpleReporter $reporter Reporter to register.
  271. * @access public
  272. */
  273. function setReporter(&$reporter) {
  274. $this->clear();
  275. $this->_reporter = &$reporter;
  276. }
  277. /**
  278. * Accessor for current reporter.
  279. * @return SimpleReporter Current reporter.
  280. * @access public
  281. */
  282. function &getReporter() {
  283. return $this->_reporter;
  284. }
  285. /**
  286. * Accessor for the Singleton resource.
  287. * @return object Global resource.
  288. * @access public
  289. * @static
  290. */
  291. function &get($resource) {
  292. if (! isset($this->_resources[$resource])) {
  293. $this->_resources[$resource] = &new $resource();
  294. }
  295. return $this->_resources[$resource];
  296. }
  297. }
  298. /**
  299. * Interrogates the stack trace to recover the
  300. * failure point.
  301. * @package SimpleTest
  302. * @subpackage UnitTester
  303. */
  304. class SimpleStackTrace {
  305. var $_prefixes;
  306. /**
  307. * Stashes the list of target prefixes.
  308. * @param array $prefixes List of method prefixes
  309. * to search for.
  310. */
  311. function SimpleStackTrace($prefixes) {
  312. $this->_prefixes = $prefixes;
  313. }
  314. /**
  315. * Extracts the last method name that was not within
  316. * Simpletest itself. Captures a stack trace if none given.
  317. * @param array $stack List of stack frames.
  318. * @return string Snippet of test report with line
  319. * number and file.
  320. * @access public
  321. */
  322. function traceMethod($stack = false) {
  323. $stack = $stack ? $stack : $this->_captureTrace();
  324. foreach ($stack as $frame) {
  325. if ($this->_frameLiesWithinSimpleTestFolder($frame)) {
  326. continue;
  327. }
  328. if ($this->_frameMatchesPrefix($frame)) {
  329. return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']';
  330. }
  331. }
  332. return '';
  333. }
  334. /**
  335. * Test to see if error is generated by SimpleTest itself.
  336. * @param array $frame PHP stack frame.
  337. * @return boolean True if a SimpleTest file.
  338. * @access private
  339. */
  340. function _frameLiesWithinSimpleTestFolder($frame) {
  341. if (isset($frame['file'])) {
  342. $path = substr(SIMPLE_TEST, 0, -1);
  343. if (strpos($frame['file'], $path) === 0) {
  344. if (dirname($frame['file']) == $path) {
  345. return true;
  346. }
  347. }
  348. }
  349. return false;
  350. }
  351. /**
  352. * Tries to determine if the method call is an assert, etc.
  353. * @param array $frame PHP stack frame.
  354. * @return boolean True if matches a target.
  355. * @access private
  356. */
  357. function _frameMatchesPrefix($frame) {
  358. foreach ($this->_prefixes as $prefix) {
  359. if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) {
  360. return true;
  361. }
  362. }
  363. return false;
  364. }
  365. /**
  366. * Grabs a current stack trace.
  367. * @return array Fulle trace.
  368. * @access private
  369. */
  370. function _captureTrace() {
  371. if (function_exists('debug_backtrace')) {
  372. return array_reverse(debug_backtrace());
  373. }
  374. return array();
  375. }
  376. }
  377. /**
  378. * @package SimpleTest
  379. * @subpackage UnitTester
  380. * @deprecated
  381. */
  382. class SimpleTestOptions extends SimpleTest {
  383. /**
  384. * @deprecated
  385. */
  386. function getVersion() {
  387. return Simpletest::getVersion();
  388. }
  389. /**
  390. * @deprecated
  391. */
  392. function ignore($class) {
  393. return Simpletest::ignore($class);
  394. }
  395. /**
  396. * @deprecated
  397. */
  398. function isIgnored($class) {
  399. return Simpletest::isIgnored($class);
  400. }
  401. /**
  402. * @deprecated
  403. */
  404. function setMockBaseClass($mock_base) {
  405. return Simpletest::setMockBaseClass($mock_base);
  406. }
  407. /**
  408. * @deprecated
  409. */
  410. function getMockBaseClass() {
  411. return Simpletest::getMockBaseClass();
  412. }
  413. /**
  414. * @deprecated
  415. */
  416. function useProxy($proxy, $username = false, $password = false) {
  417. return Simpletest::useProxy($proxy, $username, $password);
  418. }
  419. /**
  420. * @deprecated
  421. */
  422. function getDefaultProxy() {
  423. return Simpletest::getDefaultProxy();
  424. }
  425. /**
  426. * @deprecated
  427. */
  428. function getDefaultProxyUsername() {
  429. return Simpletest::getDefaultProxyUsername();
  430. }
  431. /**
  432. * @deprecated
  433. */
  434. function getDefaultProxyPassword() {
  435. return Simpletest::getDefaultProxyPassword();
  436. }
  437. }
  438. ?>