Best Atoum code snippet using boolean.testClass
Oktest.php
Source:Oktest.php
1<?php2error_reporting(E_ALL);3class Oktest {4 const VERSION = '0.0.0'; // $Release: 0.0.0 $5 static $debug = false;6 static $color_available = null; //= ! preg_match('/^WIN(32|NT)$/', PHP_OS);7 static $testclass_rexp = '/(Test|TestCase|_TC)$/';8 static $repr = 'oktest_repr';9 static $fixture_manager = null; //= new Oktest_DefaultFixtureManager()10 static $diff_command_path = '/usr/bin/diff'; // don't add any option11 const PASSED = 'passed';12 const FAILED = 'failed';13 const ERROR = 'error';14 const SKIPPED = 'skipped';15 static $custom_assertions = array(16 'not_exist' => 'oktest_assert_not_exist',17 );18 function oktest_repr($val) {19 return var_export($val, true);20 }21 function failed($msg) {22 return new Oktest_AssertionFailed($msg);23 }24 function not_thrown($exception_class) {25 throw new Oktest_AssertionFailed($exception_class." expected, but not thrown.");26 }27 function skip($reason) {28 throw new Oktest_SkipException($reason);29 }30 function run() {31 $args = func_get_args();32 $runner = new Oktest_TestRunner();33 return $runner->run_with_args($args);34 }35 function tracer() {36 return new Oktest_Tracer();37 }38 function _log($msg, $arg) {39 if (self::$debug) {40 echo '*** debug: '.$msg.var_export($arg, true)."\n";41 }42 }43 function main() {44 $app = new Oktest_MainApp();45 $app->main($argv);46 }47}48Oktest::$color_available = ! preg_match('/^WIN(32|NT)$/', PHP_OS);49///50/// utils51///52class Oktest_Utils {53 static function arr_concat(&$arr, $items) {54 foreach ($items as $item) {55 $arr[] = $item;56 }57 return $arr;58 }59 static function rm_rf($path) {60 if (is_file($path)) {61 unlink($path);62 }63 else if (is_dir($path)) {64 $items = scandir($path);65 foreach ($items as $item) {66 if ($item !== '.' && $item !== '..') {67 self::rm_rf($path.'/'.$item);68 }69 }70 rmdir($path);71 }72 else {73 // nothing74 }75 }76 /** _rformat('%r', $value) is similar to sprintf('%s', oktest_repr($value)) */77 function _rformat($format, &$args) {78 preg_match_all('/(.*?)(%[sr%])/s', $format, $matches, PREG_SET_ORDER);79 $n = 0; $i = 0; $s = '';80 $repr = Oktest::$repr;81 foreach ($matches as $m) {82 $n += strlen($m[0]);83 $s .= $m[1];84 if ($m[2] === '%r') {85 $s .= '%s'; // convert '%r' into '%s'86 $args[$i] = $repr($args[$i]);87 $i++;88 }89 else {90 $s .= $m[2];91 if ($m[2] !== '%%') $i++;92 }93 }94 $s .= substr($format, $n);95 $new_format = $s;96 return $new_format;97 }98 static function get_kwargs(&$args, $defaults=array()) {99 if (! $args) return $defaults;100 $last_index = count($args) - 1;101 if (! is_array($args[$last_index])) return $defaulst;102 $options = array_pop($args);103 if ($defaults) $options = array_merge($defaults, $options);104 return $options;105 }106 static function fnmatch_grep($pattern, $list) {107 $matched = array();108 foreach ($list as $item) {109 if (fnmatch($pattern, $item)) {110 $matched[] = $item;111 }112 }113 return $matched;114 }115 //static function pat2rexp($pattern) {116 // $metachars = '';117 // $len = strlen($pattern);118 // $rexp = '/^';119 // for ($i = 0; $i < $len; $i++) {120 // $ch = $pattern{$i};121 // if ($ch === '\\') {122 // $rexp .= '\\';123 // $rexp .= ++$i < $len ? $pattern{$i} : '\\';124 // }125 // else if ($ch === '*') {126 // $rexp .= '.*';127 // }128 // else if ($ch === '?') {129 // $rexp .= '.';130 // }131 // else {132 // $rexp .= preg_quote($ch);133 // }134 // }135 // $rexp .= '$/';136 // return $rexp;137 //}138 static function diff_u($actual, $expected) {139 if (is_file(Oktest::$diff_command_path)) {140 return self::_invoke_diff_command(Oktest::$diff_command_path, $actual, $expected);141 }142 else {143 return self::_diff_by_text_diff_library($actual, $expected);144 }145 }146 static function _invoke_diff_command($diff_command_path, $actual, $expected) {147 $tmpdir = sys_get_temp_dir();148 $tmpfile1 = tempnam($tmpdir, "actual.");149 $tmpfile2 = tempnam($tmpdir, "expected.");150 $output = null;151 $ex = null;152 try {153 file_put_contents($tmpfile1, $actual);154 file_put_contents($tmpfile2, $expected);155 $output = shell_exec("$diff_command_path -u $tmpfile2 $tmpfile1");156 $output = preg_replace('/^--- .*\n\+\+\+ .*\n/', "--- expected\n+++ actual\n", $output);157 }158 catch (Exception $ex) {159 }160 if (is_file($tmpfile1)) unlink($tmpfile1);161 if (is_file($tmpfile2)) unlink($tmpfile2);162 if ($ex) throw $ex;163 return $output;164 }165 static function _diff_by_text_diff_library($actual, $expected) {166 require_once('Text/Diff.php');167 require_once('Text/Diff/Renderer.php');168 require_once('Text/Diff/Renderer/unified.php');169 $e_lines = preg_split('/^/m', $expected);170 array_shift($e_lines);171 $a_lines = preg_split('/^/m', $actual);172 array_shift($a_lines);173 $diffobj = new Text_Diff('auto', array($e_lines, $a_lines));174 $renderer = new Text_Diff_Renderer_unified();175 $diffstr = $renderer->render($diffobj);176 $preamble = "--- expected\n+++ actual\n";177 return $preamble.$diffstr;178 }179}180function oktest_repr($val) {181 return var_export($val, true);182}183///184/// assertions185///186class Oktest_AssertionFailed extends Exception {187 function _setMessage($message) {188 $this->message = $message;189 }190}191class Oktest_SkipException extends Exception {192}193class Oktest_AssertionObject {194 function __construct($actual, $boolean=true) {195 $this->actual = $actual;196 $this->boolean = $boolean;197 $this->_done = false;198 }199 function _create($actual, $op, $expected, $boolean) {200 $obj = new self($actual, $boolean);201 if ($op === null) return $obj;202 $meth = isset(self::$operators[$op]) ? self::$operators[$op] : $op;203 return call_user_func(array($obj, $meth), $expected);204 }205 function _msg($op, $expected) {206 $repr = Oktest::$repr;207 $prefix = $this->boolean ? '' : 'NOT ';208 $msg = $prefix.'$actual '.$op.' $expected : failed.209 $actual : '.$repr($this->actual).'210 $expected: '.$repr($expected);211 return $msg;212 }213 function _msg2($op, $expected) {214 $diff_str = $this->boolean && is_string($expected)215 ? Oktest_Utils::diff_u($this->actual, $expected)216 : null;217 if (! $diff_str) return $this->_msg($op, $expected);218 $prefix = $this->boolean ? '' : 'NOT ';219 return $prefix.'$actual '.$op.' $expected : failed.'."\n".$diff_str;220 }221 function eq($expected) {222 $this->_done = true;223 $boolean = $this->actual == $expected;224 if ($boolean === $this->boolean) return $this;225 throw Oktest::failed($this->_msg2('==', $expected));226 }227 function ne($expected) {228 $this->_done = true;229 $boolean = $this->actual != $expected;230 if ($boolean === $this->boolean) return $this;231 throw Oktest::failed($this->_msg('!=', $expected));232 }233 function is($expected) {234 $this->_done = true;235 $boolean = $this->actual === $expected;236 if ($boolean === $this->boolean) return $this;237 throw Oktest::failed($this->_msg2('===', $expected));238 }239 function is_not($expected) {240 $this->_done = true;241 $boolean = $this->actual !== $expected;242 if ($boolean === $this->boolean) return $this;243 throw Oktest::failed($this->_msg('!==', $expected));244 }245 function lt($expected) {246 $this->_done = true;247 $boolean = $this->actual < $expected;248 if ($boolean === $this->boolean) return $this;249 throw Oktest::failed($this->_msg('<', $expected));250 }251 function le($expected) {252 $this->_done = true;253 $boolean = $this->actual <= $expected;254 if ($boolean === $this->boolean) return $this;255 throw Oktest::failed($this->_msg('<=', $expected));256 }257 function gt($expected) {258 $this->_done = true;259 $boolean = $this->actual > $expected;260 if ($boolean === $this->boolean) return $this;261 throw Oktest::failed($this->_msg('>', $expected));262 }263 function ge($expected) {264 $this->_done = true;265 $boolean = $this->actual >= $expected;266 if ($boolean === $this->boolean) return $this;267 throw Oktest::failed($this->_msg('>=', $expected));268 }269 static $operators = array(270 '==' => 'eq',271 '!=' => 'ne',272 '===' => 'is',273 '!==' => 'is_not',274 '<' => 'lt',275 '<=' => 'le',276 '>' => 'gt',277 '>=' => 'ge',278 );279 function in_delta($expected, $delta) {280 $this->gt($expected - $delta);281 $this->lt($expected + $delta);282 return $this;283 }284 function is_a($expected) {285 $this->_done = true;286 $boolean = $this->actual instanceof $expected;287 if ($boolean === $this->boolean) return $this;288 throw Oktest::failed($this->_msg('instanceof', $expected));289 }290 function _failed($format, $args) {291 $args = func_get_args();292 $format = array_shift($args);293 $format = Oktest_Utils::_rformat($format, $args);294 $prefix = $this->boolean ? '' : 'NOT ';295 $msg = vsprintf($prefix.$format, $args);296 return Oktest::failed($msg);297 }298 function is_true_value() {299 $this->_done = true;300 $boolean = !! $this->actual;301 if ($boolean === $this->boolean) return $this;302 throw $this->_failed('!! $actual === true : failed.303 $actual : %r', $this->actual);304 }305 function is_false_value() {306 $this->_done = true;307 $boolean = ! $this->actual;308 if ($boolean === $this->boolean) return $this;309 throw $this->_failed('!! $actual === false : failed.310 $actual : %r', $this->actual);311 }312 function is_one_of($args) { // or in()?313 $this->_done = true;314 $args = func_get_args();315 $boolean = in_array($this->actual, $args);316 if ($boolean === $this->boolean) return $this;317 throw $this->_failed('in_array($actual, $expected) : failed.318 $actual : %r319 $expected: %r', $this->actual, $args);320 }321 function match($regexp) {322 $this->_done = true;323 $boolean = !! preg_match($regexp, $this->actual);324 if ($boolean === $this->boolean) return $this;325 throw $this->_failed('preg_match(\'%s\', $actual) : failed.326 $actual : %r', $regexp, $this->actual);327 }328 function has_key($key) {329 $this->_done = true;330 $boolean = array_key_exists($key, $this->actual);331 if ($boolean === $this->boolean) return $this;332 $repr = Oktest::$repr;333 $prefix = $this->boolean ? '' : 'NOT ';334 throw $this->_failed('array_key_exists($key, $actual) : failed.335 $actual : %r336 $key : %r', $this->actual, $key);337 throw Oktest::failed($msg);338 }339 function has_attr($attr_name) {340 $this->_done = true;341 $boolean = property_exists($this->actual, $attr_name);342 if ($boolean === $this->boolean) return $this;343 $repr = Oktest::$repr;344 $prefix = $this->boolean ? '' : 'NOT ';345 throw $this->_failed('property_exists($actual, \'%s\') : failed.346 $actual : %r', $attr_name, $this->actual);347 }348 function attr($attr_name, $attr_value) {349 $this->_done = true;350 //351 $bkup = $this->boolean;352 $this->boolean = true;353 $this->has_attr($attr_name);354 $this->boolean = $bkup;355 //356 $val = $this->actual->$attr_name;357 $boolean = $this->actual->$attr_name === $attr_value;358 if ($boolean === $this->boolean) return $this;359 throw $this->_failed('$actual->%s === $expected : failed.360 $actual->%s: %r361 $expected: %r', $attr_name, $attr_name, $val, $attr_value);362 }363 function count($num) {364 $this->_done = true;365 $val = count($this->actual);366 $boolean = $val === $num;367 if ($boolean === $this->boolean) return $this;368 throw $this->_failed('count($actual) === %s : failed.369 count($actual): %s370 $actual : %r', $num, $val, $this->actual);371 }372 function throws($error_class, $error_msg=null, &$exception=null) {373 if (! $this->boolean) {374 throw new ErrorException("throws() is available only with ok(), not NG().");375 }376 $ex = null;377 try {378 $fn = $this->actual;379 $fn();380 }381 catch (Exception $ex) {382 $exception = $ex;383 $repr = Oktest::$repr;384 if (! ($ex instanceof $error_class)) {385 $msg = $error_class.' expected but '.get_class($ex)." thrown.\n'"386 .' $exception: '.$repr($ex);387 throw Oktest::failed($msg);388 }389 if ($error_msg && $ex->getMessage() !== $error_msg) {390 $bkup = $this->actual;391 $this->actual = $ex->getMessage();392 $msg = $this->_msg('==', $error_msg);393 $this->actual = $bkup;394 throw Oktest::failed($msg);395 }396 }397 if (! $ex) {398 throw Oktest::failed($error_class.' expected but nothing thrown.');399 }400 return $this;401 }402 function not_throw($error_class='Exception', $exception=null) {403 if (! $this->boolean) {404 throw new ErrorException("not_throw() is available only with ok(), not NG().");405 }406 try {407 $fn = $this->actual;408 $fn();409 }410 catch (Exception $ex) {411 $exception = $ex;412 $repr = Oktest::$repr;413 if ($ex instanceof $error_class) {414 $msg = $error_class." is not expected, but thrown.\n"415 .' $exception: '.$repr($ex);416 throw Oktest::failed($msg);417 }418 }419 return $this;420 }421 static $boolean_assertions = array(422 'is_null' => 'is_null',423 'is_string' => 'is_string',424 'is_int' => 'is_int',425 'is_float' => 'is_float',426 'is_numeric' => 'is_numeric',427 'is_bool' => 'is_bool',428 'is_scalar' => 'is_scalar',429 'is_array' => 'is_array',430 'is_object' => 'is_object',431 'is_file' => 'is_file',432 'is_dir' => 'is_dir',433 'isset' => 'isset',434 'in_array' => 'in_array',435 );436 function __call($name, $args) {437 if (isset(Oktest::$custom_assertions[$name])) {438 $func = Oktest::$custom_assertions[$name];439 array_unshift($args, $this->boolean, $this->actual);440 $errmsg = call_user_func_array($func, $args);441 if ($errmsg === null) return $this;442 throw Oktest::failed($errmsg);443 }444 else if (isset(self::$boolean_assertions[$name])) {445 $func_name = self::$boolean_assertions[$name];446 array_unshift($args, $this->actual);447 $boolean = call_user_func_array($name, $args);448 if ($boolean !== true && $boolean !== false) {449 $repr = Oktest::$repr;450 $msg = 'ERROR: '.$name.'() should return true or false, but got '.$repr($boolean);451 throw new Exception($msg);452 }453 if ($boolean === $this->boolean) return $this;454 $prefix = $this->boolean ? '' : 'NOT ';455 $repr = Oktest::$repr;456 $msg = $prefix.$name."(\$actual) : failed.\n"457 . ' $actual: '.$repr($this->actual);458 throw Oktest::failed($msg);459 }460 else {461 $method = $this->boolean ? 'ok()' : 'NG()';462 $msg = $method.'->'.$name.'(): no such assertion method.';463 throw new ErrorException($msg);464 }465 }466 function all() {467 if (! $this->boolean) {468 throw ErrorException("all() is avialable only with ok(), not NG().");469 }470 return new Oktest_IterableAssertionObject($this);471 }472}473class Oktest_IterableAssertionObject {474 function __construct($assertobj) {475 $this->_assertobj = $assertobj;476 }477 function __call($method, $args) {478 $actual = $this->_assertobj->actual;479 $i = null;480 try {481 foreach ($actual as $i=>$item) {482 call_user_func_array(array(ok ($item), $method), $args);483 }484 }485 catch (Oktest_AssertionFailed $ex) {486 if ($i !== null) {487 $ex->_setMessage('[index='.$i.'] '.$ex->getMessage());488 }489 throw $ex;490 }491 return $this;492 }493}494function ok($actual, $op=null, $expected=null) {495 return Oktest_AssertionObject::_create($actual, $op, $expected, true);496}497function NG($actual, $op=null, $expected=null) {498 return Oktest_AssertionObject::_create($actual, $op, $expected, false);499}500/** same as ok(), but intended to describe pre-condition of test. */501function pre_cond($actual, $op=null, $expected=null) {502 return Oktest_AssertionObject::_create($actual, $op, $expected, true);503}504function oktest_assert_not_exist($boolean, $actual) {505 if (is_file($actual)) $func = 'is_file';506 else if (is_dir($actual)) $func = 'is_dir';507 else $func = null;508 $result = $func === null;509 if ($result === $boolean) return null;510 $repr = Oktest::$repr;511 $errmsg = $func."(\$actual) === false : failed.\n"." \$actual: ".$repr($actual);512 return $errmsg;513}514///515/// test runner516///517class Oktest_TestRunner {518 function __construct($reporter=null) {519 if (! $reporter) $reporter = new Oktest_VerboseReporter();520 $this->reporter = $reporter;521 }522 function _get_testclasses($names_or_patterns) {523 $all_class_names = get_declared_classes();524 $class_names = array(); // list525 foreach ($names_or_patterns as $item) {526 if (preg_match('/^\/.*\/[a-z]*/', $item)) {527 $rexp = $item;528 $matched = preg_grep($rexp, $all_class_names);529 if ($matched) $class_names = array_merge($class_names, $matched);530 else trigger_error("'".$rexp."': nothing matched.", E_USER_WARNING);531 }532 else if (preg_match('/[?*]/', $item)) {533 $pattern = $item;534 $matched = Oktest_Utils::fnmatch_grep($pattern, $all_class_names);535 if ($matched) $class_names = array_merge($class_names, $matched);536 else trigger_error("'".$pattern."': nothing matched.", E_USER_WARNING);537 }538 else {539 $class_name = $item;540 $ok = in_array($class_name, $all_class_names);541 if ($ok) $class_names[] = $class_name;542 else trigger_error("'".$class_name."': no such class found.", E_USER_WARNING);543 }544 }545 return $class_names;546 }547 function _get_testnames($testclass) {548 $methods = get_class_methods($testclass);549 $testnames = array();550 if (! $methods) return $testnames;551 foreach ($methods as $name) {552 if (preg_match('/^test/', $name)) {553 $testnames[] = $name;554 }555 }556 return $testnames;557 }558 function _parse_filter($filter) {559 $arr = preg_split('/\./', $filter);560 if (count($arr) > 1) {561 $class_pattern = $arr[0]; $method_pattern = $arr[1];562 }563 else if (preg_match('/^test/', $filter)) {564 $class_pattern = null; $method_pattern = $filter;565 }566 else {567 $class_pattern = $filter; $method_pattern = null;568 }569 return array($class_pattern, $method_pattern);570 }571 function run_with_args($args) {572 $defaults = array('style'=>'verbose', 'color'=>null, 'filter'=>null);573 $kwargs = Oktest_Utils::get_kwargs($args, $defaults);574 $style = $kwargs['style'];575 $color = $kwargs['color'];576 $filter = $kwargs['filter'];577 //578 $klass = Oktest_BaseReporter::get_registered_class($style);579 if (! $klass) throw new Exception($style.": no such reporting style.");580 $this->reporter = new $klass();581 $this->reporter->color = $color;582 //583 if (! $filter) {584 $class_rexps = $args ? $args : array(Oktest::$testclass_rexp);585 $class_names = $this->_get_testclasses($class_rexps);586 $method_pat = null;587 }588 else {589 list($class_pat, $method_pat) = $this->_parse_filter($filter);590 $arg = $class_pat ? $class_pat : OKtest::$testclass_rexp;591 $class_names = $this->_get_testclasses(array($arg));592 }593 //594 $ex = null;595 try {596 $this->enter_all();597 foreach ($class_names as $testclass) {598 $this->_run_testclass($testclass, $method_pat);599 }600 }601 catch (Exception $ex) {602 }603 $this->exit_all();604 if ($ex) throw $ex;605 //606 assert('isset($this->reporter->counts)');607 $dict = $this->reporter->counts;608 return $dict[Oktest::FAILED] + $dict[Oktest::ERROR];609 }610 function _run_testclass($testclass, $method_pat=null) {611 $method_names = $this->_get_testnames($testclass);612 if ($method_pat) {613 $method_names = Oktest_Utils::fnmatch_grep($method_pat, $method_names);614 if (! $method_names) return;615 }616 //617 $ex = null;618 try {619 $this->enter_testclass($testclass);620 $this->_invoke_classmethod($testclass, 'before_all', 'setUpBeforeClass');621 foreach ($method_names as $testname) {622 $testcase = $this->_new_testcase($testclass, $testname);623 $this->_run_testcase($testclass, $testcase, $testname);624 }625 }626 catch (Exception $ex) {627 }628 $this->_invoke_classmethod($testclass, 'after_all', 'tearDownAfterClass');629 $this->exit_testclass($testclass);630 if ($ex) throw $ex;631 }632 function _invoke_classmethod($klass, $method1, $method2) {633 $method = method_exists($klass, $method1) ? $method1 :634 (method_exists($klass, $method2) ? $method2 : null);635 if ($method) {636 $s = "$klass:$method();";637 eval("$klass::$method();");638 }639 }640 function _run_testcase($testclass, $testcase, $testname) {641 $this->enter_testcase($testcase, $testname);642 $status = Oktest::PASSED;643 $exceptions = array();644 $ex = $this->_call_method($testcase, 'before', 'setUp');645 if ($ex) {646 $status = Oktest::ERROR;647 $exceptions[] = $ex;648 }649 else {650 $ex = null;651 try {652 $this->_invoke_testcase($testclass, $testcase, $testname, $exceptions);653 }654 catch (Oktest_AssertionFailed $ex) { $status = Oktest::FAILED; }655 catch (Oktest_SkipException $ex) { $status = Oktest::SKIPPED; $ex = null; }656 catch (Exception $ex) { $status = Oktest::ERROR; }657 if ($exceptions) $status = Oktest::ERROR;658 if ($ex) $exceptions[] = $ex;659 }660 $ex = $this->_call_method($testcase, 'after', 'tearDown');661 if ($ex) {662 $status = Oktest::ERROR;663 $exceptions[] = $ex;664 }665 $this->exit_testcase($testcase, $testname, $status, $exceptions);666 }667 function _invoke_testcase($testclass, $testcase, $testname, &$exceptions) {668 $injector = new Oktest_FixtureInjector($testclass);669 $injector->invoke($testcase, $testname);670 }671 //function _invoke_testcase($testclass, $testcase, $testname, &$exceptions) {672 // $fixture_names = $this->_fixture_names($testclass, $testname);673 // if (! $fixture_names) {674 // $testcase->$testname(); // may throw675 // return;676 // }677 // /// gather fixtures678 // $fixtures = array();679 // $fixture_dict = array();680 // $releasers = array();681 // $ok = true;682 // foreach ($fixture_names as $name) {683 // $provider = 'provide_'.$name;684 // $releaser = 'release_'.$name;685 // try {686 // if (! method_exists($testcase, $provider)) {687 // throw new Oktest_FixtureError($provider.'() is not defined.');688 // }689 // $val = $testcase->$provider();690 // $fixtures[] = $val;691 // $fixture_dict[$name] = $val;692 // $releasers[$name] = method_exists($testcase, $releaser) ? $releaser : null;693 // }694 // catch (Exception $ex) {695 // $ok = false;696 // $exceptions[] = $ex;697 // }698 // }699 // /// invoke test method with fixtures700 // $exception = null;701 // if ($ok) {702 // try {703 // call_user_method_array($testname, $testcase, $fixtures); // may throw704 // }705 // catch (Exception $ex) {706 // $exception = $ex;707 // }708 // }709 // /// release fixtures710 // foreach ($fixture_dict as $name=>$val) {711 // if (isset($releasers[$name])) {712 // $releaser = $releasers[$name];713 // $testcase->$releaser($val);714 // }715 // }716 // /// throw exception if thrown717 // if ($exception) throw $exception;718 //}719 //720 //function _fixture_names($testclass, $testname) {721 // $ref = new ReflectionMethod($testclass, $testname);722 // $params = $ref->getParameters();723 // if (! $params) return null;724 // $param_names = array();725 // foreach ($params as $param) {726 // $param_names[] = $param->name;727 // }728 // return $param_names;729 //}730 function _call_method($testcase, $meth1, $meth2) {731 $meth = null;732 if ($meth1 && method_exists($testcase, $meth1)) $meth = $meth1;733 else if ($meth2 && method_exists($testcase, $meth2)) $meth = $meth2;734 if ($meth) {735 try {736 $testcase->$meth();737 }738 catch (Exception $ex) {739 return $ex;740 }741 }742 return null;743 }744 function _new_testcase($testclass, $testname) {745 return new $testclass();746 }747 function enter_all() {748 $this->reporter->enter_all();749 }750 function exit_all() {751 $this->reporter->exit_all();752 }753 function enter_testclass($testclass) {754 $this->reporter->enter_testclass($testclass);755 }756 function exit_testclass($testclass) {757 $this->reporter->exit_testclass($testclass);758 }759 function enter_testcase($testcase, $testname) {760 $this->reporter->enter_testcase($testcase, $testname);761 }762 function exit_testcase($testcase, $testname, $status, $exceptions) {763 $this->reporter->exit_testcase($testcase, $testname, $status, $exceptions);764 }765}766///767/// fixture768///769class Oktest_FixtureError extends ErrorException {770}771class Oktest_FixtureNotFoundError extends Oktest_FixtureError {772}773class Oktest_LoopedDependencyError extends Oktest_FixtureError {774}775class Oktest_FixtureManager {776 function provide($name) { return null; }777 function release($name, $value) { }778}779class Oktest_DefaultFixtureManager extends Oktest_FixtureManager {780 function __construct() {781 $this->_fixtures = array();782 }783 function provide($name) {784 if ($name === 'cleaner') return new Oktest_Fixture_Cleaner();785 throw new Oktest_FixtureNotFoundError('provide_'.$name.'() not defined.');786 }787 function release($name, $value) {788 if ($name === 'cleaner') return $value->clean();789 }790}791Oktest::$fixture_manager = new Oktest_DefaultFixtureManager();792class Oktest_FixtureInjector {793 function __construct($klass) {794 $this->klass = $klass;795 $this->fixture_manager = Oktest::$fixture_manager;796 $this->_ref_cache = array(); // {"provider_name"=>ReflectionMethod}797 }798 function _resolve($fixture_name, $object) {799 $name = $fixture_name;800 if (! array_key_exists($name, $this->_resolved)) {801 $pair = $this->find($name, $object);802 if ($pair) {803 list($provider, $releaser) = $pair;804 $this->_resolved[$name] = $this->_call($provider, $object, $name);805 $this->_releasers[$name] = $releaser;806 }807 else {808 $this->_resolved[$name] = $this->fixture_manager->provide($name);809 }810 }811 return $this->_resolved[$name];812 }813 function _call($provider, $object, $fixture_name) {814 if (isset($this->_ref_cache[$provider])) {815 $ref = $this->_ref_cache[$provider];816 }817 else {818 $ref = $this->_ref_cache[$provider] = new ReflectionMethod($this->klass, $provider);819 }820 if ($ref->getNumberOfParameters() === 0) {821 return $object->$provider();822 }823 $this->_in_progress[] = $fixture_name;824 $args = array(); // list825 foreach ($ref->getParameters() as $param) {826 if ($param->isOptional()) {827 /// default value can be overrided by optional parameter of test method828 $args[] = array_key_exists($param->name, $this->_resolved)829 ? $this->_resolved[$param->name]830 : $param->getDefaultValue();831 }832 else {833 $args[] = $this->_get_fixture_value($param->name, $object);834 }835 }836 $popped = array_pop($this->_in_progress);837 if ($popped !== $fixture_name) throw new Exception("** internal error: ");838 return call_user_func_array(array($object, $provider), $args);839 }840 function _get_fixture_value($aname, $object) {841 /// if already resolved then return resolved value842 if (array_key_exists($aname, $this->_resolved)) {843 return $this->_resolved[$aname];844 }845 /// if not resolved yet then resolve it with checking dependency loop846 if (! in_array($aname, $this->_in_progress)) {847 return $this->_resolve($aname, $object);848 }849 throw $this->_looped_dependency_error($aname);850 }851 function invoke($object, $method) {852 if (get_class($object) !== $this->klass) {853 throw new ErrorException('expected '.$this->klass.' object but got '.get_class($object).' object');854 }855 ///856 $ref = new ReflectionMethod($this->klass, $method);857 if ($ref->getNumberOfParameters() === 0) {858 return $object->$method();859 }860 ///861 $this->_releasers = array('self'=>null);862 $this->_resolved = array('self'=>$object);863 $this->_in_progress = array();864 ///865 $fixture_names = array(); // list866 foreach ($ref->getParameters() as $param) {867 if ($param->isOptional()) {868 /// default value of optional parameters are part of fixtures.869 /// their values are passed into providers if necessary.870 $this->_resolved[$param->name] = $param->getDefaultValue();871 }872 else {873 $fixture_names[] = $param->name;874 }875 }876 if (! $fixture_names) {877 return $object->$method();878 }879 ///880 $ex = null;881 try {882 ///883 $fixture_values = array();884 foreach ($fixture_names as $name) {885 $fixture_values[] = $this->_resolve($name, $object);886 }887 if ($this->_in_progress) throw Exception('internal error: $in_progress='.var_export($this->_in_progress, true));888 ///889 $ret = call_user_func_array(array($object, $method), $fixture_values);890 }891 catch (Exception $ex) {892 }893 $this->_release_fixtures($object);894 if ($ex) throw $ex;895 return $ret;896 }897 function _release_fixtures($object) {898 foreach ($this->_resolved as $name=>$val) {899 if (array_key_exists($name, $this->_releasers)) {900 $releaser = $this->_releasers[$name];901 if ($releaser) $object->$releaser($val);902 }903 else {904 Oktest::$fixture_manager->release($name, $val);905 }906 }907 }908 function find($name, $object) {909 $provider = 'provide_'.$name;910 $releaser = 'release_'.$name;911 if (method_exists($object, $provider)) {912 if (! method_exists($object, $releaser)) $releaser = null;913 return array($provider, $releaser);914 }915 return null;916 }917 function _looped_dependency_error($aname) {918 $names = array_merge($this->_in_progress, array($aname));919 $pos = $this->_array_index($names, $aname);920 $loop = join('=>', array_slice($names, $pos));921 if ($pos > 0) {922 $loop = join('->', array_slice($names, 0, $pos)).'->'.$loop;923 }924 $msg = sprintf('fixture dependency is looped: '.$loop.' ('.$this->klass.')');925 return new Oktest_LoopedDependencyError($msg);926 }927 function _array_index($arr, $item) {928 foreach ($arr as $i=>$v) {929 if ($v === $item) return $i;930 }931 return -1;932 }933}934class Oktest_Fixture_Cleaner implements ArrayAccess {935 function __construct() {936 $this->items = array();937 }938 function add() {939 $this->concat(func_get_args());940 return $this;941 }942 function concat($arr) {943 //$this->items = array_merge($this->items, $arr);944 foreach ($arr as $item) {945 $this->items[] = $item;946 }947 return $this;948 }949 function clean() {950 foreach ($this->items as $path) {951 Oktest_Utils::rm_rf($path);952 }953 }954 /// implements ArrayAccess955 public function offsetSet($offset, $value) {956 if (is_null($offset)) $this->items[] = $value;957 else $this->items[$offset] = $value;958 }959 public function offsetExists($offset) {960 return isset($this->items[$offset]);961 }962 public function offsetUnset($offset) {963 unset($this->items[$offset]);964 }965 public function offsetGet($offset) {966 return isset($this->items[$offset]) ? $this->items[$offset] : null;967 }968}969///970/// reporter971///972class Oktest_Reporter {973 function enter_all() {}974 function exit_all() {}975 function enter_testclass($testclass) {}976 function exit_testclass($testclass) {}977 function enter_testcase($testcase, $testname) {}978 function exit_testcase($testcase, $testname, $status, $exceptions) {}979}980class Oktest_BaseReporter extends Oktest_Reporter {981 var $separator = "----------------------------------------------------------------------";982 var $counts;983 var $color;984 function enter_all() {985 $this->counts = array('total'=>0, Oktest::PASSED=>0, Oktest::FAILED=>0, Oktest::ERROR=>0, Oktest::SKIPPED=>0);986 $this->_filenines = array(); // {'filepath'=>['lines']}987 $this->_start_time = microtime(true);988 }989 function exit_all() {990 $end_time = microtime(true);991 $dt = $end_time - $this->_start_time;992 echo '## '.$this->_build_counts_str()993 .' '.$this->_build_elapsed_str($this->_start_time, $end_time)."\n";994 $this->_filenines = null;995 }996 function _build_elapsed_str($start, $end) {997 $dt = $end - $start;998 $min = intval($dt) / 60;999 $sec = $dt - $min;1000 return $min ? sprintf("(elapsed %d:%02.3f)", $min, $sec)1001 : sprintf("(elapsed %.3f)", $sec);1002 }1003 function _build_counts_str() {1004 $total = 0;1005 $buf = array(null);1006 foreach (array(Oktest::PASSED, Oktest::FAILED, Oktest::ERROR, Oktest::SKIPPED) as $st) {1007 $n = $this->counts[$st];1008 $total += $n;1009 $s = $st.':'.$n;1010 $buf[] = $n ? $this->colorize($s, $st) : $s;1011 }1012 $buf[0] = 'total:'.$total;1013 $this->counts['total'] = $total;1014 return join(', ', $buf);1015 }1016 function enter_testclass($testclass) {1017 $this->_tuples = array();1018 }1019 function exit_testclass($testclass) {1020 $this->report_exceptions($this->_tuples);1021 }1022 function enter_testcase($testcase, $testname) {1023 }1024 function exit_testcase($testcase, $testname, $status, $exceptions) {1025 $this->counts[$status] += 1;1026 if ($exceptions) {1027 foreach ($exceptions as $ex) {1028 $this->_tuples[] = array($testcase, $testname, $status, $ex);1029 }1030 }1031 }1032 // --------------------1033 function report_exceptions($tuples) {1034 if ($tuples) {1035 foreach ($tuples as $i=>$tuple) {1036 list($testcase, $testname, $status, $exception) = $tuple;1037 echo $this->colorize($this->separator, "separator"); echo "\n";1038 $this->report_exception($testcase, $testname, $status, $exception);1039 }1040 echo $this->colorize($this->separator, "separator"); echo "\n";1041 }1042 }1043 function indicator($status, $colorize=true) {1044 if ($status === Oktest::PASSED) $s = 'ok';1045 else if ($status === Oktest::FAILED) $s = 'Failed';1046 else if ($status === Oktest::ERROR) $s = 'ERROR';1047 else if ($status === Oktest::SKIPPED) $s = 'skipped';1048 else $s = '???';1049 return $colorize ? $this->colorize($s, $status) : $s;1050 }1051 function status_char($status, $colorize=true) {1052 if ($status === Oktest::PASSED) $s = '.';1053 else if ($status === Oktest::FAILED) $s = 'f';1054 else if ($status === Oktest::ERROR) $s = 'E';1055 else if ($status === Oktest::SKIPPED) $s = 's';1056 else $s = '?';1057 return $colorize & $status !== Oktest::PASSED ? $this->colorize($s, $status) : $s;1058 }1059 function report_exception($testcase, $testname, $status, $exception) {1060 $ex = $exception;1061 $indicator = $this->indicator($status, true);1062 echo '[', $indicator, '] ', get_class($testcase), ' > ', $testname, "\n";1063 $class_name = $ex instanceof Oktest_AssertionFailed ? 'AssertionFailed' : get_class($ex);1064 echo $class_name, ': ', $ex->getMessage(), "\n";1065 //$this->report_backtrace($ex->getTrace());1066 $trace = $ex->getTrace();1067 $item = array('file'=>$ex->getFile(), 'line'=>$ex->getLine());1068 array_unshift($trace, $item);1069 $this->report_backtrace($trace);1070 }1071 function report_backtrace($trace) {1072 foreach ($trace as $i=>$dict) {1073 if ($this->skip_p($dict)) continue;1074 $file = isset($dict['file']) ? $dict['file'] : null;1075 $line = isset($dict['line']) ? $dict['line'] : null;1076 if (isset($trace[$i+1])) {1077 $d = $trace[$i+1];1078 $func = isset($d['function']) ? $d['function'] : null;1079 $class = isset($d['class']) ? $d['class'] : null;1080 $type = isset($d['type']) ? $d['type'] : null;1081 $location = $class && $func ? ($class . $type . $func)1082 : ($class ? $class : $func);1083 }1084 else {1085 $func = $class = $type = null;1086 }1087 $this->report_backtrace_entry($file, $line, $func, $class, $type);1088 }1089 }1090 function report_backtrace_entry($file, $line, $func, $class, $type) {1091 $location = $class && $func ? ($class . $type . $func)1092 : ($class ? $class : $func);1093 if ($location) {1094 //echo ' File "', $file, '", line ', $line, ', in ', $location, "\n";1095 echo ' ', $file, ':', $line, ' in ', $location, "\n";1096 }1097 else {1098 //echo ' File "', $file, '", line ', $line, "\n";1099 echo ' ', $file, ':', $line, "\n";1100 }1101 $linestr = $this->fetch_line($file, $line);1102 if ($linestr) {1103 echo ' ', trim($linestr), "\n";1104 }1105 }1106 function fetch_line($filepath, $linenum) {1107 if (! $filepath) return null;1108 if (! isset($this->_filelines[$filepath])) {1109 $this->_filelines[$filepath] = file($filepath);1110 }1111 return $this->_filelines[$filepath][$linenum-1];1112 }1113 function skip_p($dict) {1114 if (Oktest::$debug) return false;1115 if (! isset($dict['file'])) return true;1116 if (basename($dict['file']) === 'Oktest.php') return true;1117 if (isset($dict['class'])) {1118 $class = $dict['class'];1119 if ($class === 'Oktest') return true;1120 if ($class === 'Oktest_AssertionObject' &&1121 isset($dict['function']) && $dict['function'] === '__call')1122 return true;1123 }1124 return false;1125 }1126 function colorize($s, $kind) {1127 if ($this->color === null) {1128 $this->color = Oktest::$color_available && $this->is_tty();1129 }1130 if (! $this->color) return $s;1131 if ($kind === Oktest::PASSED) return Oktest_Color::bold_green($s);1132 if ($kind === Oktest::FAILED) return Oktest_Color::bold_red($s);1133 if ($kind === Oktest::ERROR) return Oktest_Color::bold_red($s);1134 if ($kind === Oktest::SKIPPED) return Oktest_Color::bold_yellow($s);1135 if ($kind === 'separator') return Oktest_Color::red($s);1136 if ($kind === 'subject') return Oktest_Color::bold($s);1137 return Oktest_Color::bold_magenta($s);1138 }1139 function is_tty() {1140 //return posix_isatty(STDOUT);1141 return true;1142 }1143 static $registered = array(1144 'verbose' => 'Oktest_VerboseReporter',1145 'simple' => 'Oktest_SimpleReporter',1146 'plain' => 'Oktest_PlainReporter',1147 );1148 function register_class($style, $klass) {1149 self::$registered[$style] = $klass;1150 }1151 function get_registered_class($style) {1152 return isset(self::$registered[$style]) ? self::$registered[$style] : null;1153 }1154}1155class Oktest_VerboseReporter extends Oktest_BaseReporter {1156 function enter_testclass($testclass) {1157 parent::enter_testclass($testclass);1158 echo '* ', $this->colorize($testclass, 'subject'), "\n";1159 $this->_testclass = $testclass;1160 }1161 function exit_testclass($testclass) {1162 parent::exit_testclass($testclass);1163 $this->_testclass = null;1164 }1165 function enter_testcase($testcase, $testname) {1166 parent::enter_testcase($testcase, $testname);1167 $ref = new ReflectionMethod($this->_testclass, $testname);1168 $filepath = $ref->getFileName();1169 $lineno = $ref->getStartLine();1170 $linestr = $this->fetch_line($filepath, $lineno-1);1171 $linestr = trim($linestr);1172 $testtitle = $testname;1173 $testdesc = null;1174 if (preg_match('/^(?:\/\/+|#+): (.*)/', $linestr, $m)) {1175 $testdesc = $m[1];1176 if ($testdesc) $testtitle = $testdesc;1177 }1178 $this->_testdesc = $testdesc;1179 if ($this->color && $this->is_tty()) {1180 echo ' - [ ] ', $testtitle;1181 fflush(STDOUT);1182 }1183 }1184 function exit_testcase($testcase, $testname, $status, $exception) {1185 $testdesc = $this->_testdesc;1186 $this->_testdesc = null;1187 if ($testdesc) {1188 $testtitle = $testdesc;1189 $testname .= " # ".$testdesc;1190 }1191 else {1192 $testtitle = $testname;1193 }1194 parent::exit_testcase($testcase, $testname, $status, $exception);1195 if ($this->color && $this->is_tty()) {1196 $this->_clear_line();1197 fflush(STDOUT);1198 }1199 $indicator = $this->indicator($status, true);1200 echo ' - [', $indicator, '] ', $testtitle, "\n";1201 }1202 function _clear_line() {1203 //$s = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";1204 $s = "\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010";1205 echo $s, $s, $s, $s, $s, $s, $s, $s, $s, $s;1206 }1207}1208class Oktest_SimpleReporter extends Oktest_BaseReporter {1209 function enter_testclass($testclass) {1210 parent::enter_testclass($testclass);1211 echo '* ', $this->colorize($testclass, 'subject'), ': ';1212 }1213 function exit_testclass($testclass) {1214 echo "\n";1215 parent::exit_testclass($testclass);1216 }1217 function exit_testcase($testcase, $testname, $status, $exception) {1218 parent::exit_testcase($testcase, $testname, $status, $exception);1219 echo $this->status_char($status, true);1220 fflush(STDOUT);1221 }1222}1223class Oktest_PlainReporter extends Oktest_BaseReporter {1224 function exit_testclass($testclass) {1225 if ($this->_tuples) {1226 echo "\n";1227 }1228 parent::exit_testclass($testclass);1229 }1230 function exit_all() {1231 echo "\n";1232 parent::exit_all();1233 }1234 function exit_testcase($testcase, $testname, $status, $exception) {1235 parent::exit_testcase($testcase, $testname, $status, $exception);1236 echo $this->status_char($status, true);1237 fflush(STDOUT);1238 }1239}1240class Oktest_Color {1241 function bold($s) { return "\033[0;1m".$s."\033[22m"; }1242 //1243 function black($s) { return "\033[0;30m".$s."\033[0m"; }1244 function red($s) { return "\033[0;31m".$s."\033[0m"; }1245 function green($s) { return "\033[0;32m".$s."\033[0m"; }1246 function yellow($s) { return "\033[0;33m".$s."\033[0m"; }1247 function blue($s) { return "\033[0;34m".$s."\033[0m"; }1248 function magenta($s) { return "\033[0;35m".$s."\033[0m"; }1249 function cyan($s) { return "\033[0;36m".$s."\033[0m"; }1250 function white($s) { return "\033[0;37m".$s."\033[0m"; }1251 //1252 function bold_black($s) { return "\033[1;30m".$s."\033[0m"; }1253 function bold_red($s) { return "\033[1;31m".$s."\033[0m"; }1254 function bold_green($s) { return "\033[1;32m".$s."\033[0m"; }1255 function bold_yellow($s) { return "\033[1;33m".$s."\033[0m"; }1256 function bold_blue($s) { return "\033[1;34m".$s."\033[0m"; }1257 function bold_magenta($s) { return "\033[1;35m".$s."\033[0m"; }1258 function bold_cyan($s) { return "\033[1;36m".$s."\033[0m"; }1259 function bold_white($s) { return "\033[1;37m".$s."\033[0m"; }1260 //1261 function _colorize($str) { // for test data1262 $str = preg_replace('/<R>(.*?)<\/R>/', "\033[1;31m\\1\033[0m", $str);1263 $str = preg_replace('/<G>(.*?)<\/G>/', "\033[1;32m\\1\033[0m", $str);1264 $str = preg_replace('/<Y>(.*?)<\/Y>/', "\033[1;33m\\1\033[0m", $str);1265 $str = preg_replace('/<r>(.*?)<\/r>/', "\033[0;31m\\1\033[0m", $str);1266 $str = preg_replace('/<b>(.*?)<\/b>/', "\033[0;1m\\1\033[22m", $str);1267 return $str;1268 }1269}1270///1271/// tracer1272///1273class Oktest_Tracer {1274 function __construct() {1275 $this->called = array();1276 }1277 function _record($object, $method, $args, $return) {1278 $this->called[] = new Oktest_CallObject($object, $method, $args, $return);1279 return $this;1280 }1281 function trace($object, $methods=null, $values=null) {1282 $args = func_get_args();1283 if (count($args) == 0) {1284 throw ErrorException("trace() requires target object.");1285 }1286 $object = array_shift($args);1287 $values = null;1288 if ($args) {1289 $last_index = count($args) - 1;1290 $values = is_array($args[$last_index]) ? array_pop($args) : null;1291 }1292 $methods = $args ? $args : null;1293 return new Oktest_WrapperObject($this, $object, $methods, $values);1294 }1295 function fake($values) {1296 return new Oktest_FakeObject($this, $values);1297 }1298}1299class Oktest_CallObject {1300 var $object;1301 var $method;1302 var $args;1303 var $ret;1304 function __construct($object, $method, $args, $ret) {1305 $this->object = $object;1306 $this->method = $method;1307 $this->args = $args;1308 $this->ret = $ret;1309 }1310}1311class Oktest_WrapperObject {1312 var $_object;1313 var $_tracer;1314 var $_values;1315 var $_methods;1316 function __construct($tracer, $object, $methods, $values) {1317 $this->_tracer = $tracer;1318 $this->_object = $object;1319 $this->_methods = $methods ? $methods : null;1320 $this->_values = $values !== null ? $values : array();1321 }1322 function __call($method, $args) {1323 $return = array_key_exists($method, $this->_values)1324 ? $this->_values[$method]1325 : call_user_func_array(array($this->_object, $method), $args);1326 if ($this->_methods === null || in_array($method, $this->_methods)) {1327 $this->_tracer->_record($this->_object, $method, $args, $return);1328 }1329 return $return;1330 }1331 function __get($name) {1332 return array_key_exists($name, $this->_values)1333 ? $this->_values[$name]1334 : $this->_object->$name;1335 }1336 function __set($name, $value) {1337 if (array_key_exists($name, $this->_values)) {1338 $this->_values[$name] = $value;1339 }1340 else {1341 $this->_object->$name = $value;1342 }1343 }1344 function __isset($name) {1345 return array_key_exists($name, $this->_values)1346 ? isset($this->_values[$name])1347 : isset($this->_object->$name);1348 }1349 function __unset($name) {1350 if (array_key_exists($name, $this->_values)) {1351 unset($this->_values[$name]);1352 }1353 else {1354 unset($this->_object->$name);1355 }1356 }1357}1358class Oktest_FakeObject {1359 var $_values;1360 var $_tracer;1361 function __construct($tracer, $values) {1362 $this->_tracer = $tracer; // Tracer1363 $this->_values = $values; // dict1364 }1365 function __call($method, $args) {1366 $ret = array_key_exists($method, $this->_values) ? $this->_values[$method] : null;1367 $this->_tracer->_record($this, $method, $args, $ret);1368 return $ret;1369 }1370 function __get($name) {1371 return $this->_values[$name];1372 }1373 function __set($name, $value) {1374 $this->_values[$name] = $value;1375 }1376 function __isset($name) {1377 return isset($this->_values[$name]);1378 }1379 function __unset($name) {1380 unset($this->_values[$name]);1381 }1382}1383///1384/// main1385///1386class Oktest_MainApp {1387 function __construct($script=null) {1388 $this->script = $script;1389 }1390 function _new_cmdopt_parser() {1391 $parser = new Cmdopt_Parser();1392 $parser->opt('-h', '--help') ->desc('show help');1393 $parser->opt('-v', '--version') ->desc('show version');1394 $parser->opt('-s')->name('style') ->arg('style') ->desc('reporting style (verbose/simple/plain, or v/s/p)');1395 $parser->opt('-p')->name('pattern')->arg('pattern')->desc("file pattern (default '*_test.php')");1396 $parser->opt('-f')->name('filter') ->arg('pattern')->desc("filter class and/or method name (see examples below)");1397 $parser->opt( '--color')->arg(null, 'bool') ;//->desc('enable/disable colorize');1398 $parser->opt('-c')->name('color') ->desc('enable output color');1399 $parser->opt('-C')->name('nocolor') ->desc('disable output color');1400 $parser->opt('-D')->name('debug') ->desc('debug mode');1401 return $parser;1402 }1403 function run($args) {1404 $parser = $this->_new_cmdopt_parser();1405 $opts = $parser->parse_args($args);1406 $filenames = $args;1407 //1408 if ($opts['debug']) Oktest::$debug = true;1409 Oktest::_log('$opts: ', $opts);1410 Oktest::_log('$args: ', $args);1411 //1412 if ($opts['help']) {1413 $this->_show_help($parser);1414 return 0;1415 }1416 if ($opts['version']) {1417 $this->_show_version();1418 return 0;1419 }1420 //1421 if (! $args) {1422 //throw new Cmdopt_ParseError("error: missing test script or directory name.");1423 echo "*** error: missing test script or directory name.\n";1424 $this->_show_help($parser);1425 return 1;1426 }1427 //1428 $kwargs = $this->_handle_opts($opts);1429 $pattern = $opts['pattern'] ? $opts['pattern'] : '*_test.php';1430 Oktest::_log('$kwargs: ', $kwargs);1431 //1432 foreach ($filenames as $filename) {1433 if (is_dir($filename)) {1434 $this->_load_recursively($filename, $pattern);1435 }1436 else {1437 require_once($filename);1438 }1439 }1440 //1441 $num_errors = Oktest::run($kwargs);1442 Oktest::_log('$num_errors: ', $num_errors);1443 return $num_errors;1444 }1445 function _show_help($parser) {1446 echo 'Usage: php '.$this->script." [options] file [file2...]\n";1447 echo $parser->options_help();1448 echo "Example:\n";1449 echo " ## detect test srcripts in plain style\n";1450 echo " $ php Oktest.php -sp tests/*_test.php\n";1451 echo " ## detect all test srcripts under 'test' directory recursively\n";1452 echo " $ php Oktest.php -p '*_test.php' test\n";1453 echo " ## filter by test class name\n";1454 echo " $ php Oktest.php -f 'ClassName*' test\n";1455 echo " ## filter by test method name (starting with 'test')\n";1456 echo " $ php Oktest.php -f 'test_name*' test\n";1457 echo " ## filter by both class and method name\n";1458 echo " $ php Oktest.php -f 'ClassName*.test_name*' test\n";1459 }1460 function _show_version() {1461 echo Oktest::VERSION, "\n";1462 }1463 function _handle_opts($opts) {1464 $kwargs = array();1465 if ($opts['style']) {1466 $style = $opts['style'];1467 $dict = array('v'=>'verbose', 's'=>'simple', 'p'=>'plain');1468 if (isset($dict[$style])) $style = $dict[$style];1469 $klass = Oktest_BaseReporter::get_registered_class($style);1470 if (! $klass) {1471 throw new Cmdopt_ParseError("$style: no such reporting style (expected verbose/simple/plain, or v/s/p).");1472 }1473 $kwargs['style'] = $style;1474 }1475 if ($opts['color'] ) $kwargs['color'] = true;1476 if ($opts['nocolor']) $kwargs['color'] = false;1477 if ($opts['filter'] ) $kwargs['filter'] = $opts['filter'];1478 return $kwargs;1479 }1480 function _load_file_if_matched($filepath, $pattern) {1481 if (fnmatch($pattern, basename($filepath))) {1482 require_once($filepath);1483 }1484 }1485 function _load_recursively($dirpath, $pattern) {1486 foreach (scandir($dirpath) as $item) {1487 if ($item === '.' || $item === '..') continue;1488 $newpath = $dirpath.'/'.$item;1489 if (is_dir($newpath)) {1490 $this->_load_recursively($newpath, $pattern);1491 }1492 else if (is_file($newpath)) {1493 $this->_load_file_if_matched($newpath, $pattern);1494 }1495 else {1496 // nothing1497 }1498 }1499 }1500 function main($argv, $exit=true) {1501 $script = array_shift($argv);1502 $script = basename($script);1503 $this->script = $script;1504 try {1505 $num_errors = $this->run($argv);1506 $status = $num_errors;1507 }1508 catch (Cmdopt_ParseError $ex) {1509 echo $script.': '.$ex->getMessage()."\n";1510 $status = 1;1511 }1512 if ($exit) exit($status);1513 return $status;1514 }1515}1516///1517/// command option parser1518///1519class Cmdopt_ParseError extends ErrorException {1520}1521class Cmdopt_Definition {1522 var $opt_short;1523 var $opt_long;1524 var $name;1525 var $arg_name;1526 var $arg_type;1527 var $arg_optional;1528 var $multiple;1529 var $desc;1530 function get_name() {1531 if ($this->name) return $this->name;1532 if ($this->opt_long) return $this->opt_long;1533 if ($this->opt_short) return $this->opt_short;1534 return null;1535 }1536 function validate($val, $prefix) {1537 $type = $this->arg_type;1538 if ($type === 'int') {1539 if (! preg_match('/^\d+$/', $val)) {1540 throw new Cmdopt_ParseError($prefix.": int value expected.");1541 }1542 $val = intval($val);1543 }1544 else if ($type === 'float') {1545 if (! preg_match('/^\d+\.\d+$/', $val)) {1546 throw new Cmdopt_ParseError($prefix.": float value expected.");1547 }1548 $val = floatval($val);1549 }1550 else if ($type === 'bool') {1551 if (is_bool($val)) return $val;1552 if (is_null($val)) return true;1553 if (is_string($val)) {1554 if ($val === 'true' || $val === 'yes' || $val == 'on') return true;1555 if ($val === 'false' || $val === 'no' || $val == 'off') return false;1556 }1557 throw new Cmdopt_ParseError($prefix.": boolean value (true or false) expected.");1558 }1559 return $val; // TODO1560 }1561}1562class Cmdopt_Builder {1563 function __construct($def=null) {1564 if (! $def) $def = new Cmdopt_Definition();1565 $this->_def = $def;1566 }1567 function opt($opt1, $opt2=null) {1568 foreach (array($opt1, $opt2) as $opt) {1569 if (! $opt) continue;1570 if (preg_match('/^-\w$/', $opt)) {1571 $this->_def->opt_short = $opt{1};1572 }1573 else if (preg_match('/^--(\w[-\w]*)$/', $opt)) {1574 $this->_def->opt_long = substr($opt, 2);1575 }1576 else {1577 throw new ErrorException("'".$opt."': unexpected option.");1578 }1579 }1580 return $this;1581 }1582 function name($name) {1583 $this->_def->name = $name;1584 return $this;1585 return $this;1586 }1587 function arg($name, $type=null) {1588 $this->_def->arg_name = $name;1589 if ($type && ! in_array($type, array('str', 'int', 'float', 'bool'))) {1590 throw new ErrorException("'".$type."': unknown arg type (str/int/float/bool).");1591 }1592 $this->_def->arg_type = $type;1593 return $this;1594 }1595 function optional() {1596 $this->_def->arg_optional = true;1597 return $this;1598 }1599 function multiple() {1600 $this->_def->multiple = true;1601 return $this;1602 }1603 function desc($desc) {1604 $this->_def->desc = $desc;1605 return $this;1606 }1607}1608class Cmdopt_Parser {1609 function __construct() {1610 $this->_defs = array();1611 }1612 function opt($opt1, $opt2=null) {1613 $def = new Cmdopt_Definition();1614 $this->_defs[] = $def;1615 $builder = new Cmdopt_Builder($def);1616 return $builder->opt($opt1, $opt2);1617 }1618 function _get_def_by_short_name($name) {1619 foreach ($this->_defs as $def) {1620 if ($def->opt_short === $name) return $def;1621 }1622 return null;1623 }1624 function _get_def_by_long_name($name) {1625 foreach ($this->_defs as $def) {1626 if ($def->opt_long === $name) return $def;1627 }1628 return null;1629 }1630 function _new_opts() {1631 $opts = array();1632 foreach ($this->_defs as $def) {1633 $opts[$def->get_name()] = null;1634 }1635 return $opts;1636 }1637 function parse_args(&$args) {1638 $opts = $this->_new_opts();1639 while ($args) {1640 $arg = $args[0];1641 if ($arg === '--') break;1642 if (! $arg) break;1643 if ($arg{0} !== '-') break;1644 $arg = array_shift($args);1645 if (preg_match('/^--(\w[-\w]*)(?:=(.*))?$/', $arg, $m)) {1646 $this->_parse_long_opt($opts, $arg, $m);1647 }1648 else if (preg_match('/^-/', $arg)) {1649 $optstr = substr($arg, 1);1650 $this->_parse_short_opts($opts, $optstr, $args);1651 }1652 else {1653 break;1654 }1655 }1656 return $opts;1657 }1658 function _parse_long_opt(&$opts, $arg, $m) {1659 $name = $m[1];1660 //$opt_val = $m[2] === null ? true : $this->_str2value($m[2]);1661 $val = isset($m[2]) ? $m[2] : true;1662 $def = $this->_get_def_by_long_name($name);1663 if (! $def) {1664 throw $this->_err('--'.$name.': unknown option.');1665 }1666 $val = $def->validate($val, $arg);1667 $opts[$def->get_name()] = $val;1668 }1669 function _parse_short_opts(&$opts, $optstr, &$args) {1670 $len = strlen($optstr);1671 for ($j = 0; $j < $len; $j++) {1672 $ch = $optstr{$j};1673 $def = $this->_get_def_by_short_name($ch);1674 if (! $def) {1675 throw $this->_err('-'.$ch.': unknown option.');1676 }1677 $dname = $def->get_name();1678 if (! $def->arg_name) {1679 $opts[$dname] = true;1680 }1681 else if ($def->arg_optional) {1682 if ($j+1 === $len) {1683 $opts[$dname] = true;1684 }1685 else {1686 $val = substr($optstr, $j+1);1687 $opts[$dname] = $def->validate($val, '-'.$ch.' '.$val);1688 }1689 break;1690 }1691 else {1692 if ($j+1 === $len) {1693 if (! $args) {1694 throw $this->_err('-'.$ch.': argument required.');1695 }1696 $val = array_shift($args);1697 }1698 else {1699 $val = substr($optstr, $j+1);1700 }1701 $opts[$dname] = $def->validate($val, '-'.$ch.' '.$val);1702 break;1703 }1704 }1705 }1706 function _err($msg) {1707 return new Cmdopt_ParseError($msg);1708 }1709 function _str2value($str) {1710 if ($str === 'true' || $str === 'yes' || $str === 'on') return true;1711 if ($str === 'false' || $str === 'no' || $str === 'off') return false;1712 if ($str === 'null') return null;1713 if (preg_match('/^\d+$/')) return intval($str);1714 if (preg_match('/^\d+.\d+$/')) return floatval($str);1715 return $str;1716 }1717 function options_help($width=null) {1718 $pairs = array();1719 foreach ($this->_defs as $def) {1720 if (! $def->desc) continue;1721 $short = $def->opt_short;1722 $long = $def->opt_long;1723 $arg = $def->arg_name;1724 $s = $def->arg_type === 'bool' ? '[=false]' : '';1725 if ($short && $long) {1726 $s = $arg ? "-$short, --${long}=$arg"1727 : "-$short, --${long}$s";1728 }1729 else if ($short) {1730 $s = $arg ? "-$short $arg"1731 : "-$short";1732 }1733 else if ($long) {1734 $s = $arg ? " --${long}=$arg"1735 : " --${long}$s";1736 }1737 $pairs[] = array($s, $def->desc);1738 }1739 if (! $width) {1740 $width = 7; // minimum1741 foreach ($pairs as $pair) {1742 $w = strlen($pair[0]) + 2;1743 if ($width < $w) $width = $w;1744 }1745 }1746 $format = " %-".$width."s: %s\n";1747 $buf = array();1748 foreach ($pairs as $pair) {1749 $buf[] = sprintf($format, $pair[0], $pair[1]);1750 }1751 return join('', $buf);1752 }1753}1754if (isset($argv[0]) && basename($argv[0]) === basename(__FILE__)) {1755 $app = new Oktest_MainApp();1756 $app->main($argv);1757}...
TypeHelperTest.php
Source:TypeHelperTest.php
...222 $this->assertEquals($expectedResult, TypeHelper::isNumericType($type));223 }224 public function coerceTypeProvider()225 {226 $testClassInstance = new TestClass();227 $arrayInstance = array(1, 2, 3);228 $arrayOfClassInstance = array(new TestClass(), new TestClass());229 return [230 ["a", "mixed", "a"],231 [null, 'float', null],232 [1, 'float', 1.0],233 ["1", 'float', 1.0],234 [0.5, 'float', 0.5],235 ["0.5", 'float', 0.5],236 ["", 'float', null, TypeCoercionException::class],237 ["a", 'float', null, TypeCoercionException::class],238 [true, "float", null, TypeCoercionException::class],239 [false, "float", null, TypeCoercionException::class],240 [array(), "float", null, TypeCoercionException::class],241 [new TestClass(), "float", null, TypeCoercionException::class],242 [null, 'double', null],243 [1, 'double', 1.0],244 ["1", 'double', 1.0],245 [0.5, 'double', 0.5],246 ["0.5", 'double', 0.5],247 ["", 'double', null, TypeCoercionException::class],248 ["a", 'double', null, TypeCoercionException::class],249 [true, "double", null, TypeCoercionException::class],250 [false, "double", null, TypeCoercionException::class],251 [array(), "double", null, TypeCoercionException::class],252 [new TestClass(), "double", null, TypeCoercionException::class],253 [null, 'int', null],254 [1, 'int', 1],255 ["1", 'int', 1],256 ["1.5", 'int', 1],257 ["", 'int', null, TypeCoercionException::class],258 ["a", 'int', null, TypeCoercionException::class],259 [true, "int", null, TypeCoercionException::class],260 [false, "int", null, TypeCoercionException::class],261 [array(), "int", null, TypeCoercionException::class],262 [new TestClass(), "int", null, TypeCoercionException::class],263 [null, 'string', null],264 ["", "string", ""],265 ["a", "string", "a"],266 [1, "string", "1"],267 [0.5, "string", "0.5"],268 [true, "string", "true"],269 [false, "string", "false"],270 [null, 'bool', null],271 [true, "bool", true],272 [false, "bool", false],273 ["true", "bool", true],274 ["false", "bool", false],275 ["True", "bool", true],276 ["False", "bool", false],277 ["TRUE", "bool", true],278 ["FALSE", "bool", false],279 [1, "bool", true],280 [0, "bool", false],281 ["", "bool", null, TypeCoercionException::class],282 ["a", "bool", null, TypeCoercionException::class],283 [$arrayInstance, "array", $arrayInstance],284 [$arrayInstance, "int[]", $arrayInstance],285 [$arrayOfClassInstance, TestClass::class . "[]", $arrayOfClassInstance],286 [array(new TestClass(), 1), TestClass::class . "[]", null, TypeCoercionException::class],287 [$testClassInstance, TestClass::class, $testClassInstance],288 [1, TestClass::class, null, TypeCoercionException::class],289 [0.5, TestClass::class, null, TypeCoercionException::class],290 ["", TestClass::class, null, TypeCoercionException::class],291 ["a", TestClass::class, null, TypeCoercionException::class],292 [true, TestClass::class, null, TypeCoercionException::class],293 [array(), TestClass::class, null, TypeCoercionException::class],294 [array($testClassInstance), TestClass::class, null, TypeCoercionException::class]295 ];296 }297 /**298 * @dataProvider coerceTypeProvider299 * @param $value300 * @param $coercionType301 * @param $expectedValue302 */303 public function testCoerceType($value, $coercionType, $expectedValue, $expectedExceptionType = null)304 {305 if ($expectedExceptionType === null) {306 $this->assertEquals($expectedValue, TypeHelper::coerceType($value, $coercionType));307 } else {308 $this->expectException($expectedExceptionType);...
ReflectionClassConstant_basic1.phpt
Source:ReflectionClassConstant_basic1.phpt
1--TEST--2Test usage of ReflectionClassConstant methods __toString(), export(), getName(), getValue(), isPublic(), isPrivate(), isProtected(), getModifiers(), getDeclaringClass() and getDocComment().3--FILE--4<?php5function reflectClassConstant($base, $constant) {6 $constInfo = new ReflectionClassConstant($base, $constant);7 echo "**********************************\n";8 $class = is_object($base) ? get_class($base) : $base;9 echo "Reflecting on class constant $class::$constant\n\n";10 echo "__toString():\n";11 var_dump($constInfo->__toString());12 echo "export():\n";13 var_dump(ReflectionClassConstant::export($base, $constant, true));14 echo "export():\n";15 var_dump(ReflectionClassConstant::export($base, $constant, false));16 echo "getName():\n";17 var_dump($constInfo->getName());18 echo "getValue():\n";19 var_dump($constInfo->getValue());20 echo "isPublic():\n";21 var_dump($constInfo->isPublic());22 echo "isPrivate():\n";23 var_dump($constInfo->isPrivate());24 echo "isProtected():\n";25 var_dump($constInfo->isProtected());26 echo "getModifiers():\n";27 var_dump($constInfo->getModifiers());28 echo "getDeclaringClass():\n";29 var_dump($constInfo->getDeclaringClass());30 echo "getDocComment():\n";31 var_dump($constInfo->getDocComment());32 echo "\n**********************************\n";33}34class TestClass {35 public const /** My Doc comment */ PUB = true;36 /** Another doc comment */37 protected const PROT = 4;38 private const PRIV = "keepOut";39}40$instance = new TestClass();41reflectClassConstant("TestClass", "PUB");42reflectClassConstant("TestClass", "PROT");43reflectClassConstant("TestClass", "PRIV");44reflectClassConstant($instance, "PRIV");45reflectClassConstant($instance, "BAD_CONST");46?>47--EXPECTF--48**********************************49Reflecting on class constant TestClass::PUB50__toString():51string(38) "Constant [ public boolean PUB ] { 1 }52"53export():54string(38) "Constant [ public boolean PUB ] { 1 }55"56export():57Constant [ public boolean PUB ] { 1 }58NULL59getName():60string(3) "PUB"61getValue():62bool(true)63isPublic():64bool(true)65isPrivate():66bool(false)67isProtected():68bool(false)69getModifiers():70int(256)71getDeclaringClass():72object(ReflectionClass)#3 (1) {73 ["name"]=>74 string(9) "TestClass"75}76getDocComment():77string(21) "/** My Doc comment */"78**********************************79**********************************80Reflecting on class constant TestClass::PROT81__toString():82string(42) "Constant [ protected integer PROT ] { 4 }83"84export():85string(42) "Constant [ protected integer PROT ] { 4 }86"87export():88Constant [ protected integer PROT ] { 4 }89NULL90getName():91string(4) "PROT"92getValue():93int(4)94isPublic():95bool(false)96isPrivate():97bool(false)98isProtected():99bool(true)100getModifiers():101int(512)102getDeclaringClass():103object(ReflectionClass)#3 (1) {104 ["name"]=>105 string(9) "TestClass"106}107getDocComment():108string(26) "/** Another doc comment */"109**********************************110**********************************111Reflecting on class constant TestClass::PRIV112__toString():113string(45) "Constant [ private string PRIV ] { keepOut }114"115export():116string(45) "Constant [ private string PRIV ] { keepOut }117"118export():119Constant [ private string PRIV ] { keepOut }120NULL121getName():122string(4) "PRIV"123getValue():124string(7) "keepOut"125isPublic():126bool(false)127isPrivate():128bool(true)129isProtected():130bool(false)131getModifiers():132int(1024)133getDeclaringClass():134object(ReflectionClass)#3 (1) {135 ["name"]=>136 string(9) "TestClass"137}138getDocComment():139bool(false)140**********************************141**********************************142Reflecting on class constant TestClass::PRIV143__toString():144string(45) "Constant [ private string PRIV ] { keepOut }145"146export():147string(45) "Constant [ private string PRIV ] { keepOut }148"149export():150Constant [ private string PRIV ] { keepOut }151NULL152getName():153string(4) "PRIV"154getValue():155string(7) "keepOut"156isPublic():157bool(false)158isPrivate():159bool(true)160isProtected():161bool(false)162getModifiers():163int(1024)164getDeclaringClass():165object(ReflectionClass)#3 (1) {166 ["name"]=>167 string(9) "TestClass"168}169getDocComment():170bool(false)171**********************************172Fatal error: Uncaught ReflectionException: Class Constant TestClass::BAD_CONST does not exist in %s:%d173Stack trace:174#0 %s(%d): ReflectionClassConstant->__construct(Object(TestClass), 'BAD_CONST')175#1 %s(%d): reflectClassConstant(Object(TestClass), 'BAD_CONST')176#2 {main}177 thrown in %s on line %d...
testClass
Using AI Code Generation
1$test = new boolean();2$test->testClass();3$test = new boolean();4$test->testClass();5$test = new boolean();6$test->testClass();7$test = new boolean();8$test->testClass();9$test = new boolean();10$test->testClass();11$test = new boolean();12$test->testClass();13$test = new boolean();14$test->testClass();15$test = new boolean();16$test->testClass();17$test = new boolean();18$test->testClass();19$test = new boolean();20$test->testClass();21$test = new boolean();22$test->testClass();23$test = new boolean();24$test->testClass();25$test = new boolean();26$test->testClass();27$test = new boolean();28$test->testClass();29$test = new boolean();30$test->testClass();31$test = new boolean();32$test->testClass();33$test = new boolean();34$test->testClass();
testClass
Using AI Code Generation
1$boolean = new boolean();2$result = $boolean->testClass();3echo $result;4$boolean = new boolean();5$result = $boolean->testClass();6echo $result;7$boolean = new boolean();8$result = $boolean->testClass();9echo $result;10$boolean = new boolean();11$result = $boolean->testClass();12echo $result;13$boolean = new boolean();14$result = $boolean->testClass();15echo $result;16$boolean = new boolean();17$result = $boolean->testClass();18echo $result;19$boolean = new boolean();20$result = $boolean->testClass();21echo $result;22$boolean = new boolean();23$result = $boolean->testClass();24echo $result;25$boolean = new boolean();26$result = $boolean->testClass();27echo $result;28$boolean = new boolean();29$result = $boolean->testClass();30echo $result;31$boolean = new boolean();32$result = $boolean->testClass();33echo $result;34$boolean = new boolean();35$result = $boolean->testClass();36echo $result;37$boolean = new boolean();38$result = $boolean->testClass();39echo $result;40$boolean = new boolean();41$result = $boolean->testClass();42echo $result;
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Execute automation tests with testClass on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.
Test now for FreeGet 100 minutes of automation test minutes FREE!!