PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/.dev/tests/PHPUnit/TestCase.php

https://github.com/istran/core
PHP | 562 lines | 226 code | 88 blank | 248 comment | 25 complexity | ffe16cc81d5bd97cd70151914402b2ed MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. <?php
  2. // vim: set ts=4 sw=4 sts=4 et:
  3. /**
  4. * Base class for all LiteCommerce tests
  5. *
  6. * @category LiteCommerce_Tests
  7. * @package LiteCommerce_Tests
  8. * @subpackage Main
  9. * @author Ruslan R. Fazliev <rrf@x-cart.com>
  10. * @copyright Copyright (c) 2009 Ruslan R. Fazliev <rrf@x-cart.com>
  11. * @license http://www.x-cart.com/license.php LiteCommerce license
  12. * @version GIT: $Id: 904d219932da59f6b64462264f8c7fd7294e34f8 $
  13. * @link http://www.x-cart.com/
  14. * @see ____file_see____
  15. * @since 1.0.0
  16. */
  17. abstract class XLite_Tests_TestCase extends PHPUnit_Framework_TestCase
  18. {
  19. /**
  20. * Prefix for all classes with test cases
  21. */
  22. const CLASS_PREFIX = 'XLite_Tests_';
  23. const IMAP_BOX = '{mail.crtdev.local:143/imap/tls/novalidate-cert}INBOX';
  24. const IMAP_USER = 'rnd_tester';
  25. const IMAP_PASS = '7qnDjKzVoc6Qcb7b';
  26. /**
  27. * Tests range
  28. *
  29. * @var array
  30. * @access public
  31. * @see ____var_see____
  32. * @since 3.0.0
  33. */
  34. public static $testsRange = array();
  35. /**
  36. * Message length
  37. *
  38. * @var integer
  39. * @access protected
  40. * @see ____var_see____
  41. * @since 3.0.0
  42. */
  43. protected static $messageLength = 70;
  44. /**
  45. * IMAP mailbox resource
  46. *
  47. * @var resource
  48. * @access private
  49. * @see ____var_see____
  50. * @since 1.0.0
  51. */
  52. private $mailBox = null;
  53. /**
  54. * last message counter in IMAP mailbox
  55. *
  56. * @var float
  57. * @access private
  58. * @see ____var_see____
  59. * @since 1.0.0
  60. */
  61. private $lastMessage = 0;
  62. /**
  63. * Parameters registering when test starts
  64. *
  65. * @var array
  66. * @access protected
  67. * @see ____var_see____
  68. * @since 1.0.0
  69. */
  70. protected $start = array('time' => 0, 'memory' => 0);
  71. /**
  72. * Parameters registering when test ends
  73. *
  74. * @var array
  75. * @access protected
  76. * @see ____var_see____
  77. * @since 1.0.0
  78. */
  79. protected $end = array('time' => 0, 'memory' => 0);
  80. /**
  81. * Return test execution time
  82. *
  83. * @return string
  84. * @access private
  85. * @see ____func_see____
  86. * @since 1.0.0
  87. */
  88. private function getExecTime()
  89. {
  90. $time = number_format($this->end['time'] - $this->start['time'], 4);
  91. $message = trim($this->getMessage('', get_called_class(), $this->name));
  92. if (strlen($message) > self::$messageLength) {
  93. self::$messageLength = strlen($message) + 1;
  94. }
  95. return sprintf('%\'.-' . self::$messageLength. 's', trim($message))
  96. . ' ' . sprintf('%8s', $time) . ' sec .....';
  97. }
  98. /**
  99. * Return memory used by test
  100. *
  101. * @return string
  102. * @access private
  103. * @see ____func_see____
  104. * @since 1.0.0
  105. */
  106. private function getMemoryUsage()
  107. {
  108. $memory = $this->end['memory'] - $this->start['memory'];
  109. if ($memory < 0) {
  110. $memory = 0;
  111. }
  112. return sprintf('%8s', number_format($memory / 1024, 2)) . ' Kb .....';
  113. }
  114. /**
  115. * Check if we need to construct/destruct application singleton
  116. *
  117. * @param array $request request info
  118. *
  119. * @return bool
  120. * @access private
  121. * @see ____func_see____
  122. * @since 1.0.0
  123. */
  124. private function needAppInit(array $request = array())
  125. {
  126. if (empty($request)) {
  127. $request = $this->getRequest();
  128. }
  129. return $request['init_app'];
  130. }
  131. /**
  132. * Return message (common method)
  133. *
  134. * @param string $message custom part of message
  135. * @param string $class called class name
  136. * @param string $method called method name
  137. *
  138. * @return string
  139. * @access protected
  140. * @see ____func_see____
  141. * @since 1.0.0
  142. */
  143. protected function getMessage($message, $class = '', $method = '')
  144. {
  145. // Full debag trace for called method
  146. $trace = debug_backtrace();
  147. $trace = $trace[1];
  148. // Retrieve class and method names
  149. $class = str_replace(self::CLASS_PREFIX, '', empty($class) ? $trace['class'] : $class);
  150. $method = lcfirst(str_replace('test', '', empty($method) ? $trace['function'] : $method));
  151. return $class . ' ' . '[' . $method . ']. ' . $message;
  152. }
  153. /**
  154. * Return data needed to start application.
  155. * Derived class can redefine this method.
  156. * It's possible to detect current test using the $this->name variable
  157. *
  158. * @return array
  159. * @access protected
  160. * @see ____func_see____
  161. * @since 1.0.0
  162. */
  163. protected function getRequest()
  164. {
  165. // Default request
  166. $request = array(
  167. 'init_app' => true,
  168. 'method' => 'GET',
  169. 'controller' => true, // true - admin, false - customer
  170. 'data' => array(
  171. 'target' => \XLite::TARGET_DEFAULT,
  172. 'action' => '',
  173. ),
  174. 'cookies' => array(),
  175. );
  176. return $request;
  177. }
  178. /**
  179. * PHPUnit default function.
  180. * Redefine this method only if you really need to do so.
  181. * In any other cases redefine the getRequest() one
  182. *
  183. * @return void
  184. * @access protected
  185. * @see ____func_see____
  186. * @since 1.0.0
  187. */
  188. protected function setUp()
  189. {
  190. set_time_limit(0);
  191. $request = $this->getRequest();
  192. // This data will be parsed by Reqest/Router transports
  193. $GLOBALS['_SERVER']['REQUEST_METHOD'] = $request['method'];
  194. if (!empty($request['data'])) {
  195. $GLOBALS['_' . $request['method']] = $request['data'];
  196. }
  197. if (!empty($request['cookies'])) {
  198. $GLOBALS['_COOKIE'] = $request['cookies'];
  199. }
  200. // Instantiate singltons
  201. if ($this->needAppInit($request)) {
  202. $this->app = \XLite::getInstance()->run($request['controller']);
  203. }
  204. // Set customer skin
  205. \XLite\Model\Layout::getInstance()->setCustomerSkin();
  206. // Clear and restart (if need) entity manager
  207. \XLite\Core\Database::getEM()->clear();
  208. \XLite\Core\Database::getEM()->getConnection()->executeQuery('SET autocommit = 1');
  209. try {
  210. \XLite\Core\Database::getEM()->flush();
  211. } catch (\Doctrine\ORM\ORMException $e) {
  212. if ('The EntityManager is closed.' == $e->getMessage()) {
  213. \XLite\Core\Database::getInstance()->startEntityManager();
  214. xlite(true);
  215. } else {
  216. throw $e;
  217. }
  218. }
  219. \XLite\Core\Session::getInstance()->restart();
  220. // Print new line between classes
  221. $currentClass = get_called_class();
  222. if (empty(XLite_Tests_TestSuite::$currentClass) || $currentClass !== XLite_Tests_TestSuite::$currentClass) {
  223. echo PHP_EOL;
  224. XLite_Tests_TestSuite::$currentClass = $currentClass;
  225. }
  226. // Memory usage
  227. $this->start['memory'] = memory_get_usage();
  228. $this->end['memory'] = 0;
  229. // Timing
  230. $this->start['time'] = microtime(true);
  231. }
  232. /**
  233. * PHPUnit default function.
  234. * It's not recommended to redefine this method
  235. *
  236. * @return void
  237. * @access protected
  238. * @see ____func_see____
  239. * @since 1.0.0
  240. */
  241. protected function tearDown()
  242. {
  243. // Timing
  244. $this->end['time'] = microtime(true);
  245. // if ($this->needAppInit()) {
  246. // \XLite\Core\Converter::getInstance()->__destruct();
  247. // \XLite\Core\Database::getInstance()->__destruct();
  248. // $this->app->__destruct();
  249. // }
  250. // Memory usage
  251. $this->end['memory'] += memory_get_usage();
  252. echo PHP_EOL . $this->getExecTime();
  253. echo $this->getMemoryUsage();
  254. $this->writeMetricLog();
  255. }
  256. /**
  257. * Write metric log
  258. *
  259. * @return void
  260. * @access private
  261. * @see ____func_see____
  262. * @since 3.0.0
  263. */
  264. private function writeMetricLog()
  265. {
  266. $trace = debug_backtrace();
  267. $trace = $trace[0];
  268. $class = get_called_class();
  269. $method = $this->name;
  270. $class = str_replace(self::CLASS_PREFIX, '', empty($class) ? $trace['class'] : $class);
  271. $method = lcfirst(str_replace('test', '', empty($method) ? $trace['function'] : $method));
  272. $time = intval(round($this->end['time'] - $this->start['time'], 6) * 1000000);
  273. $memory = max($this->end['memory'] - $this->start['memory'], 0);
  274. XLite_Tests_MetricWriter::write($class, $method, $time, $memory);
  275. }
  276. /**
  277. * Check exception code
  278. *
  279. * @param function $func Function
  280. * @param string $class Exception class name
  281. * @param string $message Exception message
  282. *
  283. * @return void
  284. * @access protected
  285. * @see ____func_see____
  286. * @since 1.0.0
  287. */
  288. protected function checkException($func, $message, $class = '\Exception')
  289. {
  290. try {
  291. $func();
  292. $this->fail('Exception "' . $message . '" was not thrown');
  293. } catch (\Exception $exception) {
  294. $this->assertEquals($message, $exception->getMessage(), 'Check exception : "' . $message . '" message not found');
  295. $this->assertTrue($exception instanceof $class, 'Check exception : "' . $class . '" exception class not equal');
  296. }
  297. }
  298. /**
  299. * Check warning
  300. *
  301. * @param mixed $func Closure (function) or list of closures
  302. * @param string $errorCode Error code
  303. *
  304. * @return void
  305. * @access protected
  306. * @see ____func_see____
  307. * @since 3.0.0
  308. */
  309. protected function checkWarning($func, $errorCode)
  310. {
  311. if ($this->isFunction($func)) {
  312. $func = array($func);
  313. } elseif (is_array($func)) {
  314. foreach ($func as $k => $v) {
  315. if (!$this->isFunction($v)) {
  316. unset($func[$k]);
  317. }
  318. }
  319. }
  320. if (!is_array($func) || count($func) == 0) {
  321. $this->fail($this->getMessage('Argument $func is not valid'));
  322. }
  323. foreach ($func as $i => $f) {
  324. try {
  325. $f();
  326. } catch (PHPUnit_Framework_Error_Warning $exception) {
  327. $message = $this->getMessage('Check for the "' . $errorCode . '" exception:');
  328. $this->assertEquals($errorCode, substr($exception->getMessage(), 0, strlen($errorCode)), $message);
  329. continue;
  330. }
  331. $this->fail(
  332. $this->getMessage(
  333. 'The "' . $errorCode . '" exception was not thrown'
  334. . (count($func) > 1 ? (' (function #' . ($i + 1) .')') : '')
  335. )
  336. );
  337. }
  338. }
  339. /**
  340. * Check - is fuunction (closure) or not
  341. *
  342. * @param \Closure $func Function
  343. *
  344. * @return boolean
  345. * @access protected
  346. * @see ____func_see____
  347. * @since 3.0.0
  348. */
  349. protected function isFunction($func) {
  350. return is_object($func) && get_class($func) == 'Closure';
  351. }
  352. /**
  353. * Set start of emails counter
  354. *
  355. * @return void
  356. * @access public
  357. * @see ____func_see____
  358. * @since 1.0.0
  359. */
  360. public function startCheckingMail()
  361. {
  362. $this->initMailBox();
  363. $mc = imap_check($this->mailBox);
  364. $this->lastMessage = $mc->Nmsgs;
  365. $this->closeMailBox();
  366. }
  367. /**
  368. * Init mailbox
  369. *
  370. * @return void
  371. * @access private
  372. * @see ____func_see____
  373. * @since 1.0.0
  374. */
  375. private function initMailBox()
  376. {
  377. if (
  378. is_null($this->mailBox)
  379. || false === $this->mailBox
  380. ) {
  381. $this->mailBox = imap_open(self::IMAP_BOX, self::IMAP_USER, self::IMAP_PASS);
  382. }
  383. }
  384. /**
  385. * close IMAP mailbox
  386. *
  387. * @return void
  388. * @access private
  389. * @see ____func_see____
  390. * @since 1.0.0
  391. */
  392. private function closeMailBox()
  393. {
  394. imap_close($this->mailBox);
  395. $this->mailBox = null;
  396. }
  397. /**
  398. * check if there are new emails and fetch them
  399. *
  400. * @return array array of emails
  401. * @access public
  402. * @see ____func_see____
  403. * @since 1.0.0
  404. */
  405. public function finishCheckingMail()
  406. {
  407. $this->initMailBox();
  408. $mc = imap_check($this->mailBox);
  409. $emails = array();
  410. if ($mc->Nmsgs > $this->lastMessage) {
  411. for ($i = $this->lastMessage + 1; $i <= $mc->Nmsgs; $i++) {
  412. $header = @imap_fetchbody($this->mailBox, $i, '0');
  413. $body = @imap_fetchbody($this->mailBox, $i, '1');
  414. $emails[] = array(
  415. 'header' => $header,
  416. 'body' => $body,
  417. );
  418. }
  419. $this->lastMessage = $mc->Nmsgs;
  420. }
  421. $this->closeMailBox();
  422. return $emails;
  423. }
  424. /**
  425. * Do SQL query
  426. *
  427. * @param sql $sql SQL query
  428. *
  429. * @return void
  430. * @access protected
  431. * @see ____func_see____
  432. * @since 3.0.0
  433. */
  434. protected function query($sql)
  435. {
  436. \XLite\Core\Database::getEM()->getConnection()->executeQuery($sql, array());
  437. }
  438. /**
  439. * Constructs a test case with the given name.
  440. *
  441. * @param string $name
  442. * @param array $data
  443. * @param string $dataName
  444. */
  445. public function __construct($name = NULL, array $data = array(), $dataName = '')
  446. {
  447. parent::__construct($name, $data, $dataName);
  448. }
  449. /**
  450. * Run test
  451. *
  452. * @return void
  453. * @access protected
  454. * @see ____func_see____
  455. * @since 3.0.0
  456. */
  457. protected function runTest()
  458. {
  459. $shortName = lcfirst(substr($this->name, 4));
  460. if (self::$testsRange && !in_array($shortName, self::$testsRange)) {
  461. $this->markTestSkipped();
  462. } else {
  463. parent::runTest();
  464. }
  465. }
  466. protected function getProduct()
  467. {
  468. return \XLite\Core\Database::getRepo('XLite\Model\Product')->findOneByEnabled(true);
  469. }
  470. protected function getProductBySku($sku)
  471. {
  472. return \XLite\Core\Database::getRepo('XLite\Model\Product')->findOneBy(array('sku' => $sku));
  473. }
  474. }