/modules/php/Test.php

https://github.com/outbounder/php5boilerplate · PHP · 295 lines · 254 code · 21 blank · 20 comment · 22 complexity · b963620f3cf35846bf548427bd15dc60 MD5 · raw file

  1. <?php
  2. /*
  3. example usage:
  4. class MyTest extends TestCase {
  5. function testMyFeature() {
  6. $module = ...
  7. $result = $module->getResult();
  8. $this->describe("Checking if the result is not NULL")->isNotNull($result);
  9. $this->describe("Checking if the result is > 10")->isTrue($result > 10);
  10. }
  11. }
  12. die(Test::run(new OpenXTesting()));
  13. */
  14. // run multiple tests
  15. class Test {
  16. public static function run($arg) {
  17. $result = "";
  18. if(is_array($arg)) {
  19. $numOfTests = count($arg);
  20. for($i=0; $i<$numOfTests; $i++) {
  21. $result .= $arg->run();
  22. }
  23. } if(is_string($arg)){
  24. require_once($arg);
  25. $parts = explode("/", $arg);
  26. $className = str_replace(".php", "", array_pop($parts));
  27. $instance = new $className();
  28. $isntance->run();
  29. } else {
  30. $result = $arg->run();
  31. }
  32. return $result;
  33. }
  34. };
  35. // responsible for displaying the results
  36. class TestResult {
  37. private $result = "";
  38. public function __construct() {
  39. $this->result .= '
  40. <style type="text/css">
  41. body {
  42. font-family: Tahoma;
  43. font-size: 14px;
  44. }
  45. </style>
  46. ';
  47. }
  48. public function title($str) {
  49. $this->result .= '<h1 style="font-size:20px;">'.$str.'</h1>';
  50. }
  51. public function passed($str) {
  52. $this->result .= '<p style="color: #256D1B; margin: 0; padding: 0;">Passed &#187; '.$str.'</p>';
  53. }
  54. public function failed($str) {
  55. $this->result .= '<p style="color: #FF0000; font-weight: bold; margin: 0; padding: 0;">Failed &#187; '.$str.'</p>';
  56. }
  57. public function sectionStart($title) {
  58. $this->result .= '<fieldset><legend>'.$title.'</legend>';
  59. }
  60. public function sectionEnd() {
  61. $this->result .= '</fieldset>';
  62. }
  63. public function note($str) {
  64. $this->result .= '
  65. <p
  66. style="
  67. border-left: solid 10px #42A5CA;
  68. border-top: solid 1px #49C2BF;
  69. margin: 2px 0 0 0;
  70. padding: 5px 0 5px 5px;
  71. font-size: 12px;
  72. font-weight: bold;
  73. color: #42A5CA;
  74. "
  75. >'.$str.'</p>';
  76. }
  77. public function __toString() {
  78. return $this->result;
  79. }
  80. };
  81. // custom exception which help us to investigate the result of the test
  82. class TestException extends Exception {
  83. public $status;
  84. function __construct($status) {
  85. $this->status = $status;
  86. }
  87. };
  88. // the actual test class
  89. class TestCase {
  90. protected $_result;
  91. private $_skipMethods = array(
  92. "__construct",
  93. "run",
  94. "TestCase",
  95. "getTraceInformation",
  96. "processResult",
  97. "isTrue",
  98. "isFalse",
  99. "isNull",
  100. "isNotNull",
  101. "isA",
  102. "isNotA",
  103. "isEqual",
  104. "isNotEqual",
  105. "isIdentical",
  106. "isNotIdentical",
  107. "isEmptyString",
  108. "isNotEmptyString",
  109. "isMoreThen",
  110. "isLessThen",
  111. "describe"
  112. );
  113. public function __construct() {
  114. $this->_result = new TestResult();
  115. }
  116. public function run() {
  117. $this->_result->title("class ".get_class($this));
  118. $methods = get_class_methods(get_class($this));
  119. $numOfMethods = count($methods);
  120. for($i=0; $i<$numOfMethods; $i++) {
  121. $method = $methods[$i];
  122. if(!in_array($method, $this->_skipMethods)) {
  123. $this->_result->sectionStart("method : ".$method);
  124. $this->$method();
  125. $this->_result->sectionEnd();
  126. }
  127. }
  128. return $this->_result;
  129. }
  130. public function describe($str) {
  131. $this->_result->note($str);
  132. return $this;
  133. }
  134. protected function isTrue($expression, $catch = true) {
  135. if($catch) {
  136. try {
  137. if($expression) {
  138. throw new TestException(true);
  139. } else {
  140. throw new TestException(false);
  141. }
  142. } catch(TestException $e) {
  143. $this->processResult($e);
  144. }
  145. } else {
  146. if(!$expression) {
  147. throw new TestException(false);
  148. }
  149. }
  150. }
  151. protected function isFalse($expression, $catch = true) {
  152. $this->isTrue(!$expression, $catch);
  153. }
  154. protected function isNull($expression, $catch = true) {
  155. $this->isTrue($expression === NULL, $catch);
  156. }
  157. protected function isNotNull($expression, $catch = true) {
  158. $this->isTrue($expression !== NULL, $catch);
  159. }
  160. protected function isA($ob, $className) {
  161. try {
  162. $this->isNotNull($ob, false);
  163. $this->isNotNull($className, false);
  164. $this->isTrue(get_class($ob) == $className);
  165. } catch(TestException $e) {
  166. $this->processResult($e);
  167. }
  168. }
  169. protected function isNotA($ob, $className) {
  170. try {
  171. $this->isNotNull($ob, false);
  172. $this->isNotNull($className, false);
  173. $this->isTrue(get_class($ob) != $className);
  174. } catch(TestException $e) {
  175. $this->processResult($e);
  176. }
  177. }
  178. protected function isEqual($a, $b) {
  179. try {
  180. $this->isNotNull($a, false);
  181. $this->isNotNull($b, false);
  182. $this->isTrue($a == $b);
  183. } catch(TestException $e) {
  184. $this->processResult($e);
  185. }
  186. }
  187. protected function isNotEqual($a, $b) {
  188. try {
  189. $this->isNotNull($a, false);
  190. $this->isNotNull($b, false);
  191. $this->isTrue(!($a == $b));
  192. } catch(TestException $e) {
  193. $this->processResult($e);
  194. }
  195. }
  196. protected function isIdentical($a, $b) {
  197. try {
  198. $this->isNotNull($a, false);
  199. $this->isNotNull($b, false);
  200. $this->isTrue($a === $b);
  201. } catch(TestException $e) {
  202. $this->processResult($e);
  203. }
  204. }
  205. protected function isNotIdentical($a, $b) {
  206. try {
  207. $this->isNotNull($a, false);
  208. $this->isNotNull($b, false);
  209. $this->isTrue(!($a === $b));
  210. } catch(TestException $e) {
  211. $this->processResult($e);
  212. }
  213. }
  214. protected function isEmptyString($str) {
  215. try {
  216. $this->isNotNull($str, false);
  217. $this->isIdentical($str, "");
  218. } catch(TestException $e) {
  219. $this->processResult($e);
  220. }
  221. }
  222. protected function isNotEmptyString($str) {
  223. try {
  224. $this->isNotNull($str, false);
  225. $this->isNotIdentical($str, "");
  226. } catch(TestException $e) {
  227. $this->processResult($e);
  228. }
  229. }
  230. protected function isMoreThen($a, $value) {
  231. try {
  232. $this->isNotNull($a, false);
  233. $this->isTrue($a > $value);
  234. } catch(TestException $e) {
  235. $this->processResult($e);
  236. }
  237. }
  238. protected function isLessThen($a, $value) {
  239. try {
  240. $this->isNotNull($a, false);
  241. $this->isTrue($a < $value);
  242. } catch(TestException $e) {
  243. $this->processResult($e);
  244. }
  245. }
  246. private function getTraceInformation($trace) {
  247. $numOfTraces = count($trace);
  248. for($i=0; $i<$numOfTraces; $i++) {
  249. if($trace[$i]["class"] != 'TestCase' && $i > 0) {
  250. return $trace[$i-1];
  251. }
  252. }
  253. return $trace[0];
  254. }
  255. private function processResult($e) {
  256. $trace = $this->getTraceInformation($e->getTrace());
  257. if(isset($trace)) {
  258. $file = basename($trace["file"]);
  259. $resultMessage = '';
  260. $resultMessage .= '<strong>'.$file.'</strong>';
  261. $resultMessage .= ' (line: '.$trace["line"].', method: '.$trace["function"].')';
  262. if($e->status) {
  263. $this->_result->passed($resultMessage);
  264. } else {
  265. $this->_result->failed($resultMessage);
  266. }
  267. }
  268. }
  269. };
  270. ?>