CakeTestCase.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. <?php
  2. /**
  3. * CakeTestCase file
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  8. * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice
  12. *
  13. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  15. * @package Cake.TestSuite
  16. * @since CakePHP(tm) v 1.2.0.4667
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. App::uses('CakeFixtureManager', 'TestSuite/Fixture');
  20. App::uses('CakeTestFixture', 'TestSuite/Fixture');
  21. /**
  22. * CakeTestCase class
  23. *
  24. * @package Cake.TestSuite
  25. */
  26. abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
  27. /**
  28. * The class responsible for managing the creation, loading and removing of fixtures
  29. *
  30. * @var CakeFixtureManager
  31. */
  32. public $fixtureManager = null;
  33. /**
  34. * By default, all fixtures attached to this class will be truncated and reloaded after each test.
  35. * Set this to false to handle manually
  36. *
  37. * @var array
  38. */
  39. public $autoFixtures = true;
  40. /**
  41. * Set this to false to avoid tables to be dropped if they already exist
  42. *
  43. * @var boolean
  44. */
  45. public $dropTables = true;
  46. /**
  47. * Configure values to restore at end of test.
  48. *
  49. * @var array
  50. */
  51. protected $_configure = array();
  52. /**
  53. * Path settings to restore at the end of the test.
  54. *
  55. * @var array
  56. */
  57. protected $_pathRestore = array();
  58. /**
  59. * Runs the test case and collects the results in a TestResult object.
  60. * If no TestResult object is passed a new one will be created.
  61. * This method is run for each test method in this class
  62. *
  63. * @param PHPUnit_Framework_TestResult $result
  64. * @return PHPUnit_Framework_TestResult
  65. * @throws InvalidArgumentException
  66. */
  67. public function run(PHPUnit_Framework_TestResult $result = null) {
  68. if (!empty($this->fixtureManager)) {
  69. $this->fixtureManager->load($this);
  70. }
  71. $result = parent::run($result);
  72. if (!empty($this->fixtureManager)) {
  73. $this->fixtureManager->unload($this);
  74. }
  75. return $result;
  76. }
  77. /**
  78. * Called when a test case method is about to start (to be overridden when needed.)
  79. *
  80. * @param string $method Test method about to get executed.
  81. * @return void
  82. */
  83. public function startTest($method) {
  84. }
  85. /**
  86. * Called when a test case method has been executed (to be overridden when needed.)
  87. *
  88. * @param string $method Test method about that was executed.
  89. * @return void
  90. */
  91. public function endTest($method) {
  92. }
  93. /**
  94. * Overrides SimpleTestCase::skipIf to provide a boolean return value
  95. *
  96. * @param boolean $shouldSkip
  97. * @param string $message
  98. * @return boolean
  99. */
  100. public function skipIf($shouldSkip, $message = '') {
  101. if ($shouldSkip) {
  102. $this->markTestSkipped($message);
  103. }
  104. return $shouldSkip;
  105. }
  106. /**
  107. * Setup the test case, backup the static object values so they can be restored.
  108. * Specifically backs up the contents of Configure and paths in App if they have
  109. * not already been backed up.
  110. *
  111. * @return void
  112. */
  113. public function setUp() {
  114. parent::setUp();
  115. if (empty($this->_configure)) {
  116. $this->_configure = Configure::read();
  117. }
  118. if (empty($this->_pathRestore)) {
  119. $this->_pathRestore = App::paths();
  120. }
  121. if (class_exists('Router', false)) {
  122. Router::reload();
  123. }
  124. }
  125. /**
  126. * teardown any static object changes and restore them.
  127. *
  128. * @return void
  129. */
  130. public function tearDown() {
  131. parent::tearDown();
  132. App::build($this->_pathRestore, App::RESET);
  133. if (class_exists('ClassRegistry', false)) {
  134. ClassRegistry::flush();
  135. }
  136. if (!empty($this->_configure)) {
  137. Configure::clear();
  138. Configure::write($this->_configure);
  139. }
  140. if (isset($_GET['debug']) && $_GET['debug']) {
  141. ob_flush();
  142. }
  143. }
  144. /**
  145. * See CakeTestSuiteDispatcher::date()
  146. *
  147. * @param string $format format to be used.
  148. * @return string
  149. */
  150. public static function date($format = 'Y-m-d H:i:s') {
  151. return CakeTestSuiteDispatcher::date($format);
  152. }
  153. // @codingStandardsIgnoreStart PHPUnit overrides don't match CakePHP
  154. /**
  155. * Announces the start of a test.
  156. *
  157. * @param string $method Test method just started.
  158. * @return void
  159. */
  160. protected function assertPreConditions() {
  161. parent::assertPreConditions();
  162. $this->startTest($this->getName());
  163. }
  164. /**
  165. * Announces the end of a test.
  166. *
  167. * @param string $method Test method just finished.
  168. * @return void
  169. */
  170. protected function assertPostConditions() {
  171. parent::assertPostConditions();
  172. $this->endTest($this->getName());
  173. }
  174. // @codingStandardsIgnoreEnd
  175. /**
  176. * Chooses which fixtures to load for a given test
  177. *
  178. * @param string $fixture Each parameter is a model name that corresponds to a
  179. * fixture, i.e. 'Post', 'Author', etc.
  180. * @return void
  181. * @see CakeTestCase::$autoFixtures
  182. * @throws Exception when no fixture manager is available.
  183. */
  184. public function loadFixtures() {
  185. if (empty($this->fixtureManager)) {
  186. throw new Exception(__d('cake_dev', 'No fixture manager to load the test fixture'));
  187. }
  188. $args = func_get_args();
  189. foreach ($args as $class) {
  190. $this->fixtureManager->loadSingle($class);
  191. }
  192. }
  193. /**
  194. * Assert text equality, ignoring differences in newlines.
  195. * Helpful for doing cross platform tests of blocks of text.
  196. *
  197. * @param string $expected The expected value.
  198. * @param string $result The actual value.
  199. * @param message The message to use for failure.
  200. * @return boolean
  201. */
  202. public function assertTextNotEquals($expected, $result, $message = '') {
  203. $expected = str_replace(array("\r\n", "\r"), "\n", $expected);
  204. $result = str_replace(array("\r\n", "\r"), "\n", $result);
  205. return $this->assertNotEquals($expected, $result, $message);
  206. }
  207. /**
  208. * Assert text equality, ignoring differences in newlines.
  209. * Helpful for doing cross platform tests of blocks of text.
  210. *
  211. * @param string $expected The expected value.
  212. * @param string $result The actual value.
  213. * @param message The message to use for failure.
  214. * @return boolean
  215. */
  216. public function assertTextEquals($expected, $result, $message = '') {
  217. $expected = str_replace(array("\r\n", "\r"), "\n", $expected);
  218. $result = str_replace(array("\r\n", "\r"), "\n", $result);
  219. return $this->assertEquals($expected, $result, $message);
  220. }
  221. /**
  222. * Asserts that a string starts with a given prefix, ignoring differences in newlines.
  223. * Helpful for doing cross platform tests of blocks of text.
  224. *
  225. * @param string $prefix
  226. * @param string $string
  227. * @param string $message
  228. * @return boolean
  229. */
  230. public function assertTextStartsWith($prefix, $string, $message = '') {
  231. $prefix = str_replace(array("\r\n", "\r"), "\n", $prefix);
  232. $string = str_replace(array("\r\n", "\r"), "\n", $string);
  233. return $this->assertStringStartsWith($prefix, $string, $message);
  234. }
  235. /**
  236. * Asserts that a string starts not with a given prefix, ignoring differences in newlines.
  237. * Helpful for doing cross platform tests of blocks of text.
  238. *
  239. * @param string $prefix
  240. * @param string $string
  241. * @param string $message
  242. * @return boolean
  243. */
  244. public function assertTextStartsNotWith($prefix, $string, $message = '') {
  245. $prefix = str_replace(array("\r\n", "\r"), "\n", $prefix);
  246. $string = str_replace(array("\r\n", "\r"), "\n", $string);
  247. return $this->assertStringStartsNotWith($prefix, $string, $message);
  248. }
  249. /**
  250. * Asserts that a string ends with a given prefix, ignoring differences in newlines.
  251. * Helpful for doing cross platform tests of blocks of text.
  252. *
  253. * @param string $suffix
  254. * @param string $string
  255. * @param string $message
  256. * @return boolean
  257. */
  258. public function assertTextEndsWith($suffix, $string, $message = '') {
  259. $suffix = str_replace(array("\r\n", "\r"), "\n", $suffix);
  260. $string = str_replace(array("\r\n", "\r"), "\n", $string);
  261. return $this->assertStringEndsWith($suffix, $string, $message);
  262. }
  263. /**
  264. * Asserts that a string ends not with a given prefix, ignoring differences in newlines.
  265. * Helpful for doing cross platform tests of blocks of text.
  266. *
  267. * @param string $suffix
  268. * @param string $string
  269. * @param string $message
  270. * @return boolean
  271. */
  272. public function assertTextEndsNotWith($suffix, $string, $message = '') {
  273. $suffix = str_replace(array("\r\n", "\r"), "\n", $suffix);
  274. $string = str_replace(array("\r\n", "\r"), "\n", $string);
  275. return $this->assertStringEndsNotWith($suffix, $string, $message);
  276. }
  277. /**
  278. * Assert that a string contains another string, ignoring differences in newlines.
  279. * Helpful for doing cross platform tests of blocks of text.
  280. *
  281. * @param string $needle
  282. * @param string $haystack
  283. * @param string $message
  284. * @param boolean $ignoreCase
  285. * @return boolean
  286. */
  287. public function assertTextContains($needle, $haystack, $message = '', $ignoreCase = false) {
  288. $needle = str_replace(array("\r\n", "\r"), "\n", $needle);
  289. $haystack = str_replace(array("\r\n", "\r"), "\n", $haystack);
  290. return $this->assertContains($needle, $haystack, $message, $ignoreCase);
  291. }
  292. /**
  293. * Assert that a text doesn't contain another text, ignoring differences in newlines.
  294. * Helpful for doing cross platform tests of blocks of text.
  295. *
  296. * @param string $needle
  297. * @param string $haystack
  298. * @param string $message
  299. * @param boolean $ignoreCase
  300. * @return boolean
  301. */
  302. public function assertTextNotContains($needle, $haystack, $message = '', $ignoreCase = false) {
  303. $needle = str_replace(array("\r\n", "\r"), "\n", $needle);
  304. $haystack = str_replace(array("\r\n", "\r"), "\n", $haystack);
  305. return $this->assertNotContains($needle, $haystack, $message, $ignoreCase);
  306. }
  307. /**
  308. * Takes an array $expected and generates a regex from it to match the provided $string.
  309. * Samples for $expected:
  310. *
  311. * Checks for an input tag with a name attribute (contains any non-empty value) and an id
  312. * attribute that contains 'my-input':
  313. * array('input' => array('name', 'id' => 'my-input'))
  314. *
  315. * Checks for two p elements with some text in them:
  316. * array(
  317. * array('p' => true),
  318. * 'textA',
  319. * '/p',
  320. * array('p' => true),
  321. * 'textB',
  322. * '/p'
  323. * )
  324. *
  325. * You can also specify a pattern expression as part of the attribute values, or the tag
  326. * being defined, if you prepend the value with preg: and enclose it with slashes, like so:
  327. * array(
  328. * array('input' => array('name', 'id' => 'preg:/FieldName\d+/')),
  329. * 'preg:/My\s+field/'
  330. * )
  331. *
  332. * Important: This function is very forgiving about whitespace and also accepts any
  333. * permutation of attribute order. It will also allow whitespace between specified tags.
  334. *
  335. * @param string $string An HTML/XHTML/XML string
  336. * @param array $expected An array, see above
  337. * @param string $message SimpleTest failure output string
  338. * @return boolean
  339. */
  340. public function assertTags($string, $expected, $fullDebug = false) {
  341. $regex = array();
  342. $normalized = array();
  343. foreach ((array)$expected as $key => $val) {
  344. if (!is_numeric($key)) {
  345. $normalized[] = array($key => $val);
  346. } else {
  347. $normalized[] = $val;
  348. }
  349. }
  350. $i = 0;
  351. foreach ($normalized as $tags) {
  352. if (!is_array($tags)) {
  353. $tags = (string)$tags;
  354. }
  355. $i++;
  356. if (is_string($tags) && $tags{0} == '<') {
  357. $tags = array(substr($tags, 1) => array());
  358. } elseif (is_string($tags)) {
  359. $tagsTrimmed = preg_replace('/\s+/m', '', $tags);
  360. if (preg_match('/^\*?\//', $tags, $match) && $tagsTrimmed !== '//') {
  361. $prefix = array(null, null);
  362. if ($match[0] == '*/') {
  363. $prefix = array('Anything, ', '.*?');
  364. }
  365. $regex[] = array(
  366. sprintf('%sClose %s tag', $prefix[0], substr($tags, strlen($match[0]))),
  367. sprintf('%s<[\s]*\/[\s]*%s[\s]*>[\n\r]*', $prefix[1], substr($tags, strlen($match[0]))),
  368. $i,
  369. );
  370. continue;
  371. }
  372. if (!empty($tags) && preg_match('/^preg\:\/(.+)\/$/i', $tags, $matches)) {
  373. $tags = $matches[1];
  374. $type = 'Regex matches';
  375. } else {
  376. $tags = preg_quote($tags, '/');
  377. $type = 'Text equals';
  378. }
  379. $regex[] = array(
  380. sprintf('%s "%s"', $type, $tags),
  381. $tags,
  382. $i,
  383. );
  384. continue;
  385. }
  386. foreach ($tags as $tag => $attributes) {
  387. $regex[] = array(
  388. sprintf('Open %s tag', $tag),
  389. sprintf('[\s]*<%s', preg_quote($tag, '/')),
  390. $i,
  391. );
  392. if ($attributes === true) {
  393. $attributes = array();
  394. }
  395. $attrs = array();
  396. $explanations = array();
  397. $i = 1;
  398. foreach ($attributes as $attr => $val) {
  399. if (is_numeric($attr) && preg_match('/^preg\:\/(.+)\/$/i', $val, $matches)) {
  400. $attrs[] = $matches[1];
  401. $explanations[] = sprintf('Regex "%s" matches', $matches[1]);
  402. continue;
  403. } else {
  404. $quotes = '["\']';
  405. if (is_numeric($attr)) {
  406. $attr = $val;
  407. $val = '.+?';
  408. $explanations[] = sprintf('Attribute "%s" present', $attr);
  409. } elseif (!empty($val) && preg_match('/^preg\:\/(.+)\/$/i', $val, $matches)) {
  410. $quotes = '["\']?';
  411. $val = $matches[1];
  412. $explanations[] = sprintf('Attribute "%s" matches "%s"', $attr, $val);
  413. } else {
  414. $explanations[] = sprintf('Attribute "%s" == "%s"', $attr, $val);
  415. $val = preg_quote($val, '/');
  416. }
  417. $attrs[] = '[\s]+' . preg_quote($attr, '/') . '=' . $quotes . $val . $quotes;
  418. }
  419. $i++;
  420. }
  421. if ($attrs) {
  422. $permutations = $this->_arrayPermute($attrs);
  423. $permutationTokens = array();
  424. foreach ($permutations as $permutation) {
  425. $permutationTokens[] = implode('', $permutation);
  426. }
  427. $regex[] = array(
  428. sprintf('%s', implode(', ', $explanations)),
  429. $permutationTokens,
  430. $i,
  431. );
  432. }
  433. $regex[] = array(
  434. sprintf('End %s tag', $tag),
  435. '[\s]*\/?[\s]*>[\n\r]*',
  436. $i,
  437. );
  438. }
  439. }
  440. foreach ($regex as $i => $assertation) {
  441. list($description, $expressions, $itemNum) = $assertation;
  442. $matches = false;
  443. foreach ((array)$expressions as $expression) {
  444. if (preg_match(sprintf('/^%s/s', $expression), $string, $match)) {
  445. $matches = true;
  446. $string = substr($string, strlen($match[0]));
  447. break;
  448. }
  449. }
  450. if (!$matches) {
  451. $this->assertTrue(false, sprintf('Item #%d / regex #%d failed: %s', $itemNum, $i, $description));
  452. if ($fullDebug) {
  453. debug($string, true);
  454. debug($regex, true);
  455. }
  456. return false;
  457. }
  458. }
  459. $this->assertTrue(true, '%s');
  460. return true;
  461. }
  462. /**
  463. * Generates all permutation of an array $items and returns them in a new array.
  464. *
  465. * @param array $items An array of items
  466. * @return array
  467. */
  468. protected function _arrayPermute($items, $perms = array()) {
  469. static $permuted;
  470. if (empty($perms)) {
  471. $permuted = array();
  472. }
  473. if (empty($items)) {
  474. $permuted[] = $perms;
  475. } else {
  476. $numItems = count($items) - 1;
  477. for ($i = $numItems; $i >= 0; --$i) {
  478. $newItems = $items;
  479. $newPerms = $perms;
  480. list($tmp) = array_splice($newItems, $i, 1);
  481. array_unshift($newPerms, $tmp);
  482. $this->_arrayPermute($newItems, $newPerms);
  483. }
  484. return $permuted;
  485. }
  486. }
  487. // @codingStandardsIgnoreStart
  488. /**
  489. * Compatibility wrapper function for assertEquals
  490. *
  491. *
  492. * @param mixed $result
  493. * @param mixed $expected
  494. * @param string $message the text to display if the assertion is not correct
  495. * @return void
  496. */
  497. protected static function assertEqual($result, $expected, $message = '') {
  498. return self::assertEquals($expected, $result, $message);
  499. }
  500. /**
  501. * Compatibility wrapper function for assertNotEquals
  502. *
  503. * @param mixed $result
  504. * @param mixed $expected
  505. * @param string $message the text to display if the assertion is not correct
  506. * @return void
  507. */
  508. protected static function assertNotEqual($result, $expected, $message = '') {
  509. return self::assertNotEquals($expected, $result, $message);
  510. }
  511. /**
  512. * Compatibility wrapper function for assertRegexp
  513. *
  514. * @param mixed $pattern a regular expression
  515. * @param string $string the text to be matched
  516. * @param string $message the text to display if the assertion is not correct
  517. * @return void
  518. */
  519. protected static function assertPattern($pattern, $string, $message = '') {
  520. return self::assertRegExp($pattern, $string, $message);
  521. }
  522. /**
  523. * Compatibility wrapper function for assertEquals
  524. *
  525. * @param mixed $actual
  526. * @param mixed $expected
  527. * @param string $message the text to display if the assertion is not correct
  528. * @return void
  529. */
  530. protected static function assertIdentical($actual, $expected, $message = '') {
  531. return self::assertSame($expected, $actual, $message);
  532. }
  533. /**
  534. * Compatibility wrapper function for assertNotEquals
  535. *
  536. * @param mixed $actual
  537. * @param mixed $expected
  538. * @param string $message the text to display if the assertion is not correct
  539. * @return void
  540. */
  541. protected static function assertNotIdentical($actual, $expected, $message = '') {
  542. return self::assertNotSame($expected, $actual, $message);
  543. }
  544. /**
  545. * Compatibility wrapper function for assertNotRegExp
  546. *
  547. * @param mixed $pattern a regular expression
  548. * @param string $string the text to be matched
  549. * @param string $message the text to display if the assertion is not correct
  550. * @return void
  551. */
  552. protected static function assertNoPattern($pattern, $string, $message = '') {
  553. return self::assertNotRegExp($pattern, $string, $message);
  554. }
  555. protected function assertNoErrors() {
  556. }
  557. /**
  558. * Compatibility wrapper function for setExpectedException
  559. *
  560. * @param mixed $expected the name of the Exception or error
  561. * @param string $message the text to display if the assertion is not correct
  562. * @return void
  563. */
  564. protected function expectError($expected = false, $message = '') {
  565. if (!$expected) {
  566. $expected = 'Exception';
  567. }
  568. $this->setExpectedException($expected, $message);
  569. }
  570. /**
  571. * Compatibility wrapper function for setExpectedException
  572. *
  573. * @param mixed $expected the name of the Exception
  574. * @param string $message the text to display if the assertion is not correct
  575. * @return void
  576. */
  577. protected function expectException($name = 'Exception', $message = '') {
  578. $this->setExpectedException($name, $message);
  579. }
  580. /**
  581. * Compatibility wrapper function for assertSame
  582. *
  583. * @param mixed $first
  584. * @param mixed $second
  585. * @param string $message the text to display if the assertion is not correct
  586. * @return void
  587. */
  588. protected static function assertReference(&$first, &$second, $message = '') {
  589. return self::assertSame($first, $second, $message);
  590. }
  591. /**
  592. * Compatibility wrapper for assertIsA
  593. *
  594. * @param string $object
  595. * @param string $type
  596. * @param string $message
  597. * @return void
  598. */
  599. protected static function assertIsA($object, $type, $message = '') {
  600. return self::assertInstanceOf($type, $object, $message);
  601. }
  602. /**
  603. * Compatibility function to test if value is between an acceptable range
  604. *
  605. * @param mixed $result
  606. * @param mixed $expected
  607. * @param mixed $margin the rage of acceptation
  608. * @param string $message the text to display if the assertion is not correct
  609. * @return void
  610. */
  611. protected static function assertWithinMargin($result, $expected, $margin, $message = '') {
  612. $upper = $result + $margin;
  613. $lower = $result - $margin;
  614. return self::assertTrue((($expected <= $upper) && ($expected >= $lower)), $message);
  615. }
  616. /**
  617. * Compatibility function for skipping.
  618. *
  619. * @param boolean $condition Condition to trigger skipping
  620. * @param string $message Message for skip
  621. * @return boolean
  622. */
  623. protected function skipUnless($condition, $message = '') {
  624. if (!$condition) {
  625. $this->markTestSkipped($message);
  626. }
  627. return $condition;
  628. }
  629. // @codingStandardsIgnoreEnd
  630. }