Source for file Fixture.php

Documentation is available at Fixture.php

  1. <?php
  2. /**
  3. * FIT Fixture
  4. *
  5. * $Id$
  6. *
  7. * @author Luis A. Floreani <luis.floreani@gmail.com>
  8. * @author gERD Schaufelberger <gerd@php-tools.net>
  9. * @package FIT
  10. * @subpackage Fixture
  11. * @license LGPL http://www.gnu.org/copyleft/lesser.html
  12. * @copyright Copyright (c) 2002-2005 Cunningham & Cunningham, Inc.
  13. */
  14. /**
  15. * path to user's fixtures
  16. */
  17. if( !defined( 'PHPFIT_FIXTURE_DIR' ) ) {
  18. define( 'PHPFIT_FIXTURE_DIR', '.' );
  19. }
  20.  
  21. /**
  22. * load counter
  23. */
  24. include_once 'PHPFIT/Counts.php';
  25.  
  26. /**
  27. * load scienttific double class
  28. */
  29. include_once 'PHPFIT/ScientificDouble.php';
  30.  
  31. /**
  32. * load timer class
  33. */
  34. include_once 'PHPFIT/RunTime.php';
  35.  
  36. /**
  37. * FIT Fixture
  38. *
  39. * @version 0.1.0
  40. * @package FIT
  41. * @subpackage Fixture
  42. */
  43. class PHPFIT_Fixture {
  44.  
  45. /**
  46. * make the include folder available for user's fixtures
  47. * @var array
  48. */
  49. protected $backgroundColor = array(
  50. 'passed' => '#cfffcf',
  51. 'failed' => '#ffcfcf',
  52. 'ignored' => '#efefef',
  53. 'error' => '#ffffcf',
  54. );
  55.  
  56. /**
  57. * collecting information of this fixture
  58. * @var array
  59. */
  60. public $summary = array();
  61. /**
  62. * count what?
  63. * @var object
  64. */
  65. public $counts;
  66. /**
  67. * construtor
  68. *
  69. * instanciate counter
  70. */
  71. function __construct() {
  72. $this->counts = new PHPFIT_Counts();
  73. }
  74.  
  75. /**
  76. * Traverse all tables
  77. *
  78. * Tables are packed in Parse-objects
  79. *
  80. * @param Parse $tables
  81. */
  82. public function doTables( $tables ) {
  83.  
  84. $this->summary['run date'] = date( 'F d Y H:i:s.' );
  85. $this->summary['run elapsed time'] = new PHPFIT_RunTime();
  86.  
  87. // no tables left
  88. if( $tables == null ) {
  89. return;
  90. }
  91. // iterate through all tables
  92. while( $tables != null ) {
  93. $fixtureName = $this->fixtureName( $tables );
  94. if( $fixtureName == null ) {
  95. $tables = $tables->more;
  96. continue;
  97. }
  98. try {
  99. $fixture = $this->getLinkedFixtureWithArgs( $tables );
  100. $fixture->doTable( $tables );
  101. }
  102. catch( Exception $e ) {
  103. $this->exception( $fixtureName, $e );
  104. }
  105. $tables = $tables->more;
  106. }
  107. }
  108.  
  109. /**
  110. * iterate through table
  111. *
  112. * @param Parse $table
  113. * @see doRows()
  114. */
  115. public function doTable( $table )
  116. {
  117. $this->doRows( $table->parts->more );
  118. }
  119.  
  120. /**
  121. * iterate through rows
  122. *
  123. * @param Parse $rows
  124. * @see doRow()
  125. */
  126. public function doRows( $rows )
  127. {
  128. while( $rows != null ) {
  129. $more = $rows->more;
  130. $this->doRow( $rows );
  131. $rows = $more;
  132. }
  133. }
  134.  
  135. /**
  136. * iterate through cells
  137. *
  138. * @param Parse $row
  139. * @see doCells()
  140. */
  141. public function doRow( $row )
  142. {
  143. $this->doCells( $row->parts );
  144. }
  145. /**
  146. * process cells
  147. *
  148. * Generic processing of all upcoming cells. Actually, this method
  149. * just iterates through them and delegates to doCell()
  150. *
  151. * This method may be overwritten by a subclass (ActionFixture)
  152. *
  153. * @param object $cells A parse object
  154. * @return void
  155. * @see doCell()
  156. */
  157. public function doCells( $cells )
  158. {
  159. while( $cells ) {
  160. try {
  161. $this->doCell( $cells );
  162. }
  163. catch( Exception $e ) {
  164. $this->exception( $cells, $e );
  165. }
  166. $cells = $cells->more;
  167. }
  168. }
  169. /**
  170. * process a single cell
  171. *
  172. * Generic processing of a table cell. Well, this function
  173. * just ignores cells.
  174. *
  175. * This method may be overwritten by a subclass (ColumnFixture)
  176. *
  177. * @param object $cell A parse object
  178. * @return void
  179. */
  180. public function doCell( $cell )
  181. {
  182. $this->ignore( $cell );
  183. }
  184.  
  185. /**
  186. * find the name of the fixture to be executed
  187. *
  188. * @param parse $tables
  189. * @return string $name of the fixure
  190. */
  191. public function fixtureName( $tables )
  192. {
  193. return $tables->at( 0, 0, 0 );
  194. }
  195.  
  196. /**
  197. * get a fixture with arguments
  198. *
  199. * @param Parse tables
  200. * @return object Fixture
  201. * @see loadFixture()
  202. */
  203. protected function getLinkedFixtureWithArgs( $tables )
  204. {
  205. $header = $tables->at( 0, 0, 0 );
  206. $fixture = $this->loadFixture( $header->text() );
  207. $fixture->counts = $this->counts;
  208. $fixture->summary = $this->summary;
  209. return $fixture;
  210. }
  211.  
  212. /**
  213. * load a fixture by java-stylish name (dot-sparated)
  214. *
  215. * A fixture name might be something like: eg.net.Simulator. This will
  216. * load eg/net/Simulator.php and intanciates the clss eg_net_Simulator. The path name
  217. * is realtive to the basic fixture dir.
  218. *
  219. * It also supports loading standard fixtures. They are recognized by the prefix: "fit."
  220. * Those fixtures are maped to the corresponding class.
  221. *
  222. * @param string fixtureName
  223. * @return object Fixture
  224. */
  225. public function loadFixture( $fixtureName )
  226. {
  227. // load a FIT standard fixture
  228. if( strncmp( 'fit.', $fixtureName, 4 ) == 0 ) {
  229. // strip leading "fit."
  230. $fixtureName = substr( $fixtureName, 4 );
  231. $class = array( 'PHPFIT', 'Fixture' );
  232. // strip Fixture from fixtureName
  233. array_push( $class, str_replace( 'Fixture', '', $fixtureName ) );
  234. /*
  235. $pos = strpos( $fixtureName, 'Fixture' );
  236. if( $pos !== false ) {
  237. $fixtureName = substr( $fixtureName, $pos, 7 );
  238. }
  239. array_push( $class, $fixtureName );
  240. */
  241. $file = implode( '/', $class );
  242. $class = implode( '_', $class );
  243. }
  244. else {
  245. $class = str_replace( '.', '_', $fixtureName );
  246. $file = PHPFIT_FIXTURE_DIR . '/' . str_replace( '_', '/', $class );
  247. }
  248. // load class
  249. if( !include_once $file . '.php' ) {
  250. throw new Exception( 'Could not load Fixture ' . $fixtureName . 'from ' . $file . '.php' );
  251. }
  252. // instanciate
  253. $fix = new $class();
  254. return $fix;
  255. }
  256.  
  257. /**
  258. * check whether the value of a cell matches
  259. *
  260. * @param Parse $cell,
  261. * @param TypeAdapter $a
  262. * @return bool true on success, false otherwise
  263. */
  264. public function checkCell( $cell, $a )
  265. {
  266. $text = $cell->text();
  267. if( $text == '' ) {
  268. // there is no adapter
  269. if( $a == null ) {
  270. $this->info( $cell, 'error' );
  271. return false;
  272. }
  273. try {
  274. $this->info( $cell, $a->toString( $a->get() ) );
  275. }
  276. catch( Exception $e ) {
  277. $this->info( $cell, 'error' );
  278. }
  279. return true;
  280. }
  281. if( $a == null ) {
  282. $this->ignore( $cell );
  283. return true;
  284. }
  285. if( strncmp( $text, 'error', 5 ) == 0 ) {
  286. try {
  287. $result = $a->invoke();
  288. $this->wrong( $cell, $a->toString() );
  289. }
  290. catch( Exception $e ) {
  291. $this->right( $cell );
  292. }
  293. return true;
  294. }
  295. try {
  296. // the value of the attribute or the return value of the method
  297. $result = $a->get();
  298. if( $a->equals( $a->parse( $text ), $result ) ) {
  299. $this->right( $cell );
  300. }
  301. else {
  302. $result = $this->fixBoolToString( $result );
  303. $this->wrong( $cell, $a->toString( $result ) );
  304. }
  305. }
  306. catch( Exception $e ) {
  307. $this->exception($cell, $e);
  308. }
  309. return true;
  310. }
  311. /**
  312. * convert a boolean value to corresponding string
  313. *
  314. * @param bool $bool a boolean value
  315. * @return string "true" or "false"
  316. */
  317. public function fixBoolToString( $bool )
  318. {
  319. if( !is_bool( $bool ) ) {
  320. return $bool;
  321. }
  322. if( $result ) {
  323. return 'true';
  324. }
  325. return 'false';
  326. }
  327. /**
  328. * transform an exception to a cell error
  329. *
  330. * @param object $cell Parse object
  331. * @param object $e Exception
  332. * @see error()
  333. */
  334. public function exception( $cell, $e )
  335. {
  336. $this->error( $cell, $e->getMessage() );
  337. }
  338.  
  339. /**
  340. * place an error text into a cell
  341. *
  342. * @param object $cell Parse object
  343. * @param string $message
  344. */
  345. public function error( $cell, $message )
  346. {
  347. $cell->body = $cell->text() . ': '. $this->escape( $message );
  348. $cell->addToTag( ' bgcolor=" '. $this->backgroundColor['error'] . '\"' );
  349. $this->counts->exceptions++;
  350. }
  351.  
  352. /**
  353. * parse value from cell
  354. *
  355. * @param string s
  356. * @param string type
  357. * @return mixed (object or string)
  358. */
  359. public function parse( $s, $type )
  360. {
  361. if( $type == 'ScientificDouble' ) {
  362. return PHPFIT_ScientificDouble::valueOf( $s );
  363. }
  364. return $s;
  365. }
  366. /**
  367. * Add annotation to cell: right
  368. *
  369. * @param Parse c$ell
  370. * @param string type
  371. * @return mixed (object or string)
  372. */
  373. public function right( $cell )
  374. {
  375. $cell->addToTag( ' bgcolor="' . $this->backgroundColor['passed'] . '"' );
  376. $this->counts->right++;
  377. }
  378.  
  379. /**
  380. * @param Parse cell
  381. * @param string actual
  382. */
  383. public function wrong( $cell, $actual = false )
  384. {
  385. $cell->addToTag( ' bgcolor="' . $this->backgroundColor['failed'] . '"' );
  386. $cell->body = $this->escape( $cell->text() );
  387. $this->counts->wrong++;
  388. if( $actual !== false ) {
  389. $cell->addToBody( $this->label( 'expected' ) . '<hr />' . $this->escape( $actual ) . $this->label( 'actual' ) );
  390. }
  391. }
  392. /**
  393. * @param Parse cell
  394. * @param string message
  395. */
  396. public function info( $cell, $message )
  397. {
  398. $str = $this->infoS( $message );
  399. $cell->addToBody( $str );
  400. }
  401. /**
  402. * @param string message
  403. * @return string
  404. */
  405. public function infoS( $message ) {
  406. return ' <span style="color:#808080;">' . $this->escape( $message ) . '</span>';
  407. }
  408. /**
  409. * @param Parse cell
  410. */
  411.  
  412. public function ignore ($cell) {
  413. $cell->addToTag( ' bgcolor="' . $this->backgroundColor['ignored'] . '"' );
  414. $this->counts->ignores++;
  415. }
  416. /**
  417. * @param string string
  418. * @return string
  419. */
  420. public function label( $string ) {
  421. return ' <span style="color:#c08080;font-style:italic;font-size:small;">' . $string . '</span>';
  422. }
  423. /**
  424. * @param string string
  425. * @return string
  426. */
  427. public function escape($string) {
  428. $string = str_replace('&', '&amp;', $string);
  429. $string = str_replace('<', '&lt;', $string);
  430. $string = str_replace(' ', ' &nbsp;', $string);
  431. $string = str_replace('\r\n', '<br />', $string);
  432. $string = str_replace('\r', '<br />', $string);
  433. $string = str_replace('\n', '<br />', $string);
  434. return $string;
  435. }
  436. /**
  437. * receive member variable's type specification
  438. *
  439. * Use the helper property typeDict to figure out what type
  440. * a member variable or return value of a member function is
  441. *
  442. * Type is one of:
  443. * - integer
  444. * - string
  445. * - array
  446. * - object
  447. * - object:CLASSNAME
  448. * - callable
  449. *
  450. * @todo As PHP does automatica type conversation, I reckon this can be spared
  451. * @param string $name of property or method
  452. * @param bool $method check for return type of method
  453. * @return string $type
  454. */
  455. public function getType( $name, $method = false ) {
  456. // method
  457. if( $method ) {
  458. if( !method_exists( $this, $name ) ) {
  459. throw new Exception( 'Method does not exist! ' .get_class( $this ) . '->' . $name );
  460. return null;
  461. }
  462. $name .= '()';
  463. }
  464. // property
  465. else {
  466. if( !property_exists( $this, $name ) ) {
  467. throw new Exception( 'Property does not exist! ' .get_class( $this ) . '->' . $name );
  468. return null;
  469. }
  470. }
  471. if( !isset( $this->typeDict[$name] ) ) {
  472. throw new Exception( 'Property has no definition in $typeDict! ' . get_class( $this ) . '->' . $name );
  473. return null;
  474. }
  475. return $this->typeDict[$name];
  476. }
  477. /**
  478. * CamelCaseString auxiliary function
  479. *
  480. * @todo This looks quite fragile - consider using preg_replace
  481. * @param string $string
  482. * @return string
  483. */
  484. public static function camel( $string )
  485. {
  486. while( ( $pos = stripos($string, ' ' ) ) !== false ) {
  487. $characterUpper = strtoupper( $string[$pos+1] );
  488. $string[$pos+1] = $characterUpper;
  489. $string[$pos] = "&";
  490. }
  491. $string = str_replace('&', '', $string);
  492. return $string;
  493. }
  494. }
  495. ?>

Documentation generated on Sun, 02 Apr 2006 23:20:51 +0000 by phpDocumentor 1.3.0RC5