PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/script/lib/PHPUnit/Util/Test.php

https://bitbucket.org/renaatdemuynck/chamilo
PHP | 488 lines | 271 code | 55 blank | 162 comment | 41 complexity | cdd8fa82748194e81f838b61387af146 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2002-2011, Sebastian Bergmann <sebastian@phpunit.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @package PHPUnit
  38. * @subpackage Util
  39. * @author Sebastian Bergmann <sebastian@phpunit.de>
  40. * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
  41. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42. * @link http://www.phpunit.de/
  43. * @since File available since Release 3.0.0
  44. */
  45. /**
  46. * Test helpers.
  47. *
  48. * @package PHPUnit
  49. * @subpackage Util
  50. * @author Sebastian Bergmann <sebastian@phpunit.de>
  51. * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
  52. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  53. * @version Release: 3.5.9
  54. * @link http://www.phpunit.de/
  55. * @since Class available since Release 3.0.0
  56. */
  57. class PHPUnit_Util_Test
  58. {
  59. const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
  60. const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
  61. private static $annotationCache = array();
  62. protected static $templateMethods = array('setUp', 'assertPreConditions', 'assertPostConditions', 'tearDown');
  63. /**
  64. * @param PHPUnit_Framework_Test $test
  65. * @param boolean $asString
  66. * @return mixed
  67. */
  68. public static function describe(PHPUnit_Framework_Test $test, $asString = TRUE)
  69. {
  70. if ($asString)
  71. {
  72. if ($test instanceof PHPUnit_Framework_SelfDescribing)
  73. {
  74. return $test->toString();
  75. }
  76. else
  77. {
  78. return get_class($test);
  79. }
  80. }
  81. else
  82. {
  83. if ($test instanceof PHPUnit_Framework_TestCase)
  84. {
  85. return array(get_class($test), $test->getName());
  86. }
  87. else
  88. if ($test instanceof PHPUnit_Framework_SelfDescribing)
  89. {
  90. return array('', $test->toString());
  91. }
  92. else
  93. {
  94. return array('', get_class($test));
  95. }
  96. }
  97. }
  98. /**
  99. * Returns the expected exception for a test.
  100. *
  101. * @param string $className
  102. * @param string $methodName
  103. * @return array
  104. * @since Method available since Release 3.3.6
  105. */
  106. public static function getExpectedException($className, $methodName)
  107. {
  108. $reflector = new ReflectionMethod($className, $methodName);
  109. $docComment = $reflector->getDocComment();
  110. if (preg_match(self :: REGEX_EXPECTED_EXCEPTION, $docComment, $matches))
  111. {
  112. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  113. $class = $matches[1];
  114. $code = 0;
  115. $message = '';
  116. if (isset($matches[2]))
  117. {
  118. $message = trim($matches[2]);
  119. }
  120. else
  121. if (isset($annotations['method']['expectedExceptionMessage']))
  122. {
  123. $message = $annotations['method']['expectedExceptionMessage'][0];
  124. }
  125. if (isset($matches[3]))
  126. {
  127. $code = (int) $matches[3];
  128. }
  129. else
  130. if (isset($annotations['method']['expectedExceptionCode']))
  131. {
  132. $code = (int) $annotations['method']['expectedExceptionCode'][0];
  133. }
  134. return array('class' => $class, 'code' => $code, 'message' => $message);
  135. }
  136. return FALSE;
  137. }
  138. /**
  139. * Returns the provided data for a method.
  140. *
  141. * @param string $className
  142. * @param string $methodName
  143. * @param string $docComment
  144. * @return mixed array|Iterator when a data provider is specified and exists
  145. * false when a data provider is specified and does not exist
  146. * null when no data provider is specified
  147. * @since Method available since Release 3.2.0
  148. */
  149. public static function getProvidedData($className, $methodName)
  150. {
  151. $reflector = new ReflectionMethod($className, $methodName);
  152. $docComment = $reflector->getDocComment();
  153. $data = NULL;
  154. if (preg_match(self :: REGEX_DATA_PROVIDER, $docComment, $matches))
  155. {
  156. $dataProviderMethodNameNamespace = explode('\\', $matches[1]);
  157. $leaf = explode('::', array_pop($dataProviderMethodNameNamespace));
  158. $dataProviderMethodName = array_pop($leaf);
  159. if (! empty($dataProviderMethodNameNamespace))
  160. {
  161. $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\';
  162. }
  163. else
  164. {
  165. $dataProviderMethodNameNamespace = '';
  166. }
  167. if (! empty($leaf))
  168. {
  169. $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
  170. }
  171. else
  172. {
  173. $dataProviderClassName = $className;
  174. }
  175. $dataProviderClass = new ReflectionClass($dataProviderClassName);
  176. $dataProviderMethod = $dataProviderClass->getMethod($dataProviderMethodName);
  177. if ($dataProviderMethod->isStatic())
  178. {
  179. $object = NULL;
  180. }
  181. else
  182. {
  183. $object = $dataProviderClass->newInstance();
  184. }
  185. if ($dataProviderMethod->getNumberOfParameters() == 0)
  186. {
  187. $data = $dataProviderMethod->invoke($object);
  188. }
  189. else
  190. {
  191. $data = $dataProviderMethod->invoke($object, $methodName);
  192. }
  193. }
  194. if ($data !== NULL)
  195. {
  196. foreach ($data as $key => $value)
  197. {
  198. if (! is_array($value))
  199. {
  200. throw new InvalidArgumentException(sprintf('Data set %s is invalid.', is_int($key) ? '#' . $key : '"' . $key . '"'));
  201. }
  202. }
  203. }
  204. return $data;
  205. }
  206. /**
  207. * @param string $className
  208. * @param string $methodName
  209. * @return array
  210. * @throws ReflectionException
  211. * @since Method available since Release 3.4.0
  212. */
  213. public static function parseTestMethodAnnotations($className, $methodName = '')
  214. {
  215. if (! isset(self :: $annotationCache[$className]))
  216. {
  217. $class = new ReflectionClass($className);
  218. self :: $annotationCache[$className] = self :: parseAnnotations($class->getDocComment());
  219. }
  220. if (! empty($methodName) && ! isset(self :: $annotationCache[$className . '::' . $methodName]))
  221. {
  222. $method = new ReflectionMethod($className, $methodName);
  223. self :: $annotationCache[$className . '::' . $methodName] = self :: parseAnnotations($method->getDocComment());
  224. }
  225. return array('class' => self :: $annotationCache[$className],
  226. 'method' => ! empty($methodName) ? self :: $annotationCache[$className . '::' . $methodName] : array());
  227. }
  228. /**
  229. * @param string $docblock
  230. * @return array
  231. * @since Method available since Release 3.4.0
  232. */
  233. private static function parseAnnotations($docblock)
  234. {
  235. $annotations = array();
  236. if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docblock, $matches))
  237. {
  238. $numMatches = count($matches[0]);
  239. for($i = 0; $i < $numMatches; ++ $i)
  240. {
  241. $annotations[$matches['name'][$i]][] = $matches['value'][$i];
  242. }
  243. }
  244. return $annotations;
  245. }
  246. /**
  247. * Returns the backup settings for a test.
  248. *
  249. * @param string $className
  250. * @param string $methodName
  251. * @return array
  252. * @since Method available since Release 3.4.0
  253. */
  254. public static function getBackupSettings($className, $methodName)
  255. {
  256. return array('backupGlobals' => self :: getBooleanAnnotationSetting($className, $methodName, 'backupGlobals'),
  257. 'backupStaticAttributes' => self :: getBooleanAnnotationSetting($className, $methodName, 'backupStaticAttributes'));
  258. }
  259. /**
  260. * Returns the dependencies for a test class or method.
  261. *
  262. * @param string $className
  263. * @param string $methodName
  264. * @return array
  265. * @since Method available since Release 3.4.0
  266. */
  267. public static function getDependencies($className, $methodName)
  268. {
  269. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  270. $dependencies = array();
  271. if (isset($annotations['class']['depends']))
  272. {
  273. $dependencies = $annotations['class']['depends'];
  274. }
  275. if (isset($annotations['method']['depends']))
  276. {
  277. $dependencies = array_merge($dependencies, $annotations['method']['depends']);
  278. }
  279. return array_unique($dependencies);
  280. }
  281. /**
  282. * Returns the error handler settings for a test.
  283. *
  284. * @param string $className
  285. * @param string $methodName
  286. * @return boolean
  287. * @since Method available since Release 3.4.0
  288. */
  289. public static function getErrorHandlerSettings($className, $methodName)
  290. {
  291. return self :: getBooleanAnnotationSetting($className, $methodName, 'errorHandler');
  292. }
  293. /**
  294. * Returns the groups for a test class or method.
  295. *
  296. * @param string $className
  297. * @param string $methodName
  298. * @return array
  299. * @since Method available since Release 3.2.0
  300. */
  301. public static function getGroups($className, $methodName = '')
  302. {
  303. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  304. $groups = array();
  305. if (isset($annotations['method']['author']))
  306. {
  307. $groups = $annotations['method']['author'];
  308. }
  309. else
  310. if (isset($annotations['class']['author']))
  311. {
  312. $groups = $annotations['class']['author'];
  313. }
  314. if (isset($annotations['class']['group']))
  315. {
  316. $groups = array_merge($groups, $annotations['class']['group']);
  317. }
  318. if (isset($annotations['method']['group']))
  319. {
  320. $groups = array_merge($groups, $annotations['method']['group']);
  321. }
  322. return array_unique($groups);
  323. }
  324. /**
  325. * Returns the tickets for a test class or method.
  326. *
  327. * @param string $className
  328. * @param string $methodName
  329. * @return array
  330. * @since Method available since Release 3.4.0
  331. */
  332. public static function getTickets($className, $methodName)
  333. {
  334. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  335. $tickets = array();
  336. if (isset($annotations['class']['ticket']))
  337. {
  338. $tickets = $annotations['class']['ticket'];
  339. }
  340. if (isset($annotations['method']['ticket']))
  341. {
  342. $tickets = array_merge($tickets, $annotations['method']['ticket']);
  343. }
  344. return array_unique($tickets);
  345. }
  346. /**
  347. * Returns the output buffering settings for a test.
  348. *
  349. * @param string $className
  350. * @param string $methodName
  351. * @return boolean
  352. * @since Method available since Release 3.4.0
  353. */
  354. public static function getOutputBufferingSettings($className, $methodName)
  355. {
  356. return self :: getBooleanAnnotationSetting($className, $methodName, 'outputBuffering');
  357. }
  358. /**
  359. * Returns the process isolation settings for a test.
  360. *
  361. * @param string $className
  362. * @param string $methodName
  363. * @return boolean
  364. * @since Method available since Release 3.4.1
  365. */
  366. public static function getProcessIsolationSettings($className, $methodName)
  367. {
  368. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  369. if (isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']))
  370. {
  371. return TRUE;
  372. }
  373. else
  374. {
  375. return FALSE;
  376. }
  377. }
  378. /**
  379. * Returns the preserve global state settings for a test.
  380. *
  381. * @param string $className
  382. * @param string $methodName
  383. * @return boolean
  384. * @since Method available since Release 3.4.0
  385. */
  386. public static function getPreserveGlobalStateSettings($className, $methodName)
  387. {
  388. return self :: getBooleanAnnotationSetting($className, $methodName, 'preserveGlobalState');
  389. }
  390. /**
  391. * @param string $className
  392. * @param string $methodName
  393. * @param string $settingName
  394. * @return boolean
  395. * @since Method available since Release 3.4.0
  396. */
  397. private static function getBooleanAnnotationSetting($className, $methodName, $settingName)
  398. {
  399. $annotations = self :: parseTestMethodAnnotations($className, $methodName);
  400. $result = NULL;
  401. if (isset($annotations['class'][$settingName]))
  402. {
  403. if ($annotations['class'][$settingName][0] == 'enabled')
  404. {
  405. $result = TRUE;
  406. }
  407. else
  408. if ($annotations['class'][$settingName][0] == 'disabled')
  409. {
  410. $result = FALSE;
  411. }
  412. }
  413. if (isset($annotations['method'][$settingName]))
  414. {
  415. if ($annotations['method'][$settingName][0] == 'enabled')
  416. {
  417. $result = TRUE;
  418. }
  419. else
  420. if ($annotations['method'][$settingName][0] == 'disabled')
  421. {
  422. $result = FALSE;
  423. }
  424. }
  425. return $result;
  426. }
  427. }