From 8d8001272a4ee9891f6877e636a9bb47eaced52e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 12 Sep 2012 14:57:58 +0200 Subject: [PATCH] using Nette Tester --- .gitignore | 2 + .travis.yml | 4 + composer.json | 3 + tests/Nette/bootstrap.php | 19 +- tests/RunTests.bat | 2 +- tests/Test/Assert.php | 488 ------------------------------------ tests/Test/RunTests.php | 51 ---- tests/Test/TestCase.php | 334 ------------------------ tests/Test/TestHelpers.php | 158 ------------ tests/Test/TestRunner.php | 260 ------------------- tests/Test/ViewCoverage.php | 237 ----------------- tests/run-tests.sh | 4 +- 12 files changed, 14 insertions(+), 1548 deletions(-) create mode 100644 .gitignore delete mode 100644 tests/Test/Assert.php delete mode 100644 tests/Test/RunTests.php delete mode 100644 tests/Test/TestCase.php delete mode 100644 tests/Test/TestHelpers.php delete mode 100644 tests/Test/TestRunner.php delete mode 100644 tests/Test/ViewCoverage.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..de4a392c33 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor +/composer.lock diff --git a/.travis.yml b/.travis.yml index 25497d5dc3..d54402ea38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,10 @@ before_script: - tar xzf memcached-1.4.14.tar.gz - sh -c "cd memcached-1.4.14 && ./configure && make && ./memcached -d" > /dev/null +# Install Nette Tester + - curl -s http://getcomposer.org/installer | php + - php composer.phar install --dev + # PHP Memcache extension - echo n | pecl install memcache > /dev/null diff --git a/composer.json b/composer.json index 1766abeeff..ff6d40be03 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,9 @@ "require": { "php": ">=5.3.0" }, + "require-dev": { + "nette/tester": "@dev" + }, "autoload": { "files": ["Nette/loader.php"] }, diff --git a/tests/Nette/bootstrap.php b/tests/Nette/bootstrap.php index 478437faba..a819a8e671 100644 --- a/tests/Nette/bootstrap.php +++ b/tests/Nette/bootstrap.php @@ -7,16 +7,12 @@ * @package Nette\Test */ -require __DIR__ . '/../Test/TestHelpers.php'; -require __DIR__ . '/../Test/Assert.php'; + +require __DIR__ . '/../../vendor/nette/tester/Tester/bootstrap.php'; require __DIR__ . '/../../Nette/loader.php'; // configure environment -error_reporting(E_ALL | E_STRICT); -ini_set('display_errors', TRUE); -ini_set('html_errors', FALSE); -ini_set('log_errors', FALSE); date_default_timezone_set('Europe/Prague'); @@ -35,17 +31,6 @@ TestHelpers::purge(TEMP_DIR); -// catch unexpected errors/warnings/notices -set_error_handler(function($severity, $message, $file, $line) { - if (($severity & error_reporting()) === $severity) { - $e = new ErrorException($message, 0, $severity, $file, $line); - echo "Error: $message in $file:$line\nStack trace:\n" . $e->getTraceAsString(); - exit(TestCase::CODE_ERROR); - } - return FALSE; -}); - - $_SERVER = array_intersect_key($_SERVER, array_flip(array('PHP_SELF', 'SCRIPT_NAME', 'SERVER_ADDR', 'SERVER_SOFTWARE', 'HTTP_HOST', 'DOCUMENT_ROOT', 'OS', 'argc', 'argv'))); $_SERVER['REQUEST_TIME'] = 1234567890; $_ENV = $_GET = $_POST = array(); diff --git a/tests/RunTests.bat b/tests/RunTests.bat index bbecbeb00a..9877a291ea 100644 --- a/tests/RunTests.bat +++ b/tests/RunTests.bat @@ -1 +1 @@ -@php.exe "%~dp0Test\RunTests.php" -p php-cgi.exe -c "%~dp0php.ini-win" -j 20 -log "%~dp0test.log" %* +@php.exe "%~dp0..\vendor\nette\tester\Tester\RunTests.phpc" -p php-cgi.exe -c "%~dp0php.ini-win" -j 20 -log "%~dp0test.log" %* diff --git a/tests/Test/Assert.php b/tests/Test/Assert.php deleted file mode 100644 index b807737a24..0000000000 --- a/tests/Test/Assert.php +++ /dev/null @@ -1,488 +0,0 @@ -getMessage()); - } - } - - - - /** - * Checks if the function throws exception. - * @param callable - * @param string class - * @param string message - * @return void - */ - public static function throws($function, $class, $message = NULL) - { - try { - call_user_func($function); - self::doFail('Expected exception'); - } catch (Exception $e) { - Assert::exception($class, $message, $e); - } - } - - - - /** - * Checks if the function throws exception. - * @param callable - * @param int - * @param string message - * @return void - */ - public static function error($function, $level, $message = NULL) - { - $catched = NULL; - set_error_handler(function($severity, $message, $file, $line) use (& $catched) { - if (($severity & error_reporting()) === $severity) { - if ($catched) { - echo "\nUnexpected error $message in $file:$line"; - exit(TestCase::CODE_FAIL); - } - $catched = array($severity, $message); - } - }); - call_user_func($function); - restore_error_handler(); - - if (!$catched) { - self::doFail('Expected error'); - } - if ($catched[0] !== $level) { - $consts = get_defined_constants(TRUE); - foreach ($consts['Core'] as $name => $val) { - if ($catched[0] === $val && substr($name, 0, 2) === 'E_') { - $catched[0] = $name; - } - if ($level === $val && substr($name, 0, 2) === 'E_') { - $level = $name; - } - } - self::doFail('Failed asserting that ' . $catched[0] . ' is ' . $level); - } - if ($message) { - self::match($message, $catched[1]); - } - } - - - - /** - * Failed assertion - * @return void - */ - public static function fail($message) - { - self::doFail($message); - } - - - - /** - * Initializes shutdown handler. - * @return void - */ - public static function handler($handler) - { - ob_start(); - register_shutdown_function($handler); - } - - - - /** - * Compares results using mask: - * %a% one or more of anything except the end of line characters - * %a?% zero or more of anything except the end of line characters - * %A% one or more of anything including the end of line characters - * %A?% zero or more of anything including the end of line characters - * %s% one or more white space characters except the end of line characters - * %s?% zero or more white space characters except the end of line characters - * %S% one or more of characters except the white space - * %S?% zero or more of characters except the white space - * %c% a single character of any sort (except the end of line) - * %d% one or more digits - * %d?% zero or more digits - * %i% signed integer value - * %f% floating point number - * %h% one or more HEX digits - * %ns% PHP namespace - * %[..]% reg-exp - * @param string - * @param string - * @return bool - */ - public static function match($expected, $actual) - { - $expected = rtrim(preg_replace("#[\t ]+\n#", "\n", str_replace("\r\n", "\n", $expected))); - $actual = rtrim(preg_replace("#[\t ]+\n#", "\n", str_replace("\r\n", "\n", $actual))); - - $re = strtr($expected, array( - '%a%' => '[^\r\n]+', // one or more of anything except the end of line characters - '%a?%'=> '[^\r\n]*', // zero or more of anything except the end of line characters - '%A%' => '.+', // one or more of anything including the end of line characters - '%A?%'=> '.*', // zero or more of anything including the end of line characters - '%s%' => '[\t ]+', // one or more white space characters except the end of line characters - '%s?%'=> '[\t ]*', // zero or more white space characters except the end of line characters - '%S%' => '\S+', // one or more of characters except the white space - '%S?%'=> '\S*', // zero or more of characters except the white space - '%c%' => '[^\r\n]', // a single character of any sort (except the end of line) - '%d%' => '[0-9]+', // one or more digits - '%d?%'=> '[0-9]*', // zero or more digits - '%i%' => '[+-]?[0-9]+', // signed integer value - '%f%' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', // floating point number - '%h%' => '[0-9a-fA-F]+',// one or more HEX digits - '%ns%'=> '(?:[_0-9a-zA-Z\\\\]+\\\\|N)?',// PHP namespace - '%ds%'=> '[\\\\/]', // directory separator - '%[^' => '[^', // reg-exp - '%[' => '[', // reg-exp - ']%' => ']+', // reg-exp - '%(' => '(?:', // reg-exp - ')%' => ')', // reg-exp - ')?%' => ')?', // reg-exp - - '.' => '\.', '\\' => '\\\\', '+' => '\+', '*' => '\*', '?' => '\?', '[' => '\[', '^' => '\^', // preg quote - ']' => '\]', '$' => '\$', '(' => '\(', ')' => '\)', '{' => '\{', '}' => '\}', '=' => '\=', '!' => '\!', - '>' => '\>', '<' => '\<', '|' => '\|', ':' => '\:', '-' => '\-', "\x00" => '\000', '#' => '\#', - )); - - $old = ini_set('pcre.backtrack_limit', '5000000'); - $res = preg_match("#^$re$#s", $actual); - ini_set('pcre.backtrack_limit', $old); - if ($res === FALSE || preg_last_error()) { - throw new Exception("Error while executing regular expression. (PREG Error Code " . preg_last_error() . ")"); - } - if (!$res) { - self::log($expected, $actual); - self::doFail('Failed asserting that ' . self::dump($actual) . ' matches expected ' . self::dump($expected)); - } - } - - - - /** - * Returns message and file and line from call stack. - * @param string - * @return void - */ - private static function doFail($message) - { - $trace = debug_backtrace(); - while (isset($trace[0]['file']) && $trace[0]['file'] === __FILE__) { - array_shift($trace); - } - while ($trace) { - if (isset($trace[0]['file'], $trace[0]['line'])) { - $message .= "\nin " . implode(DIRECTORY_SEPARATOR, array_slice(explode(DIRECTORY_SEPARATOR, $trace[0]['file']), -3)) . ':' . $trace[0]['line']; - } - array_shift($trace); - } - echo "\n$message"; - exit(TestCase::CODE_FAIL); - } - - - - /** - * Dumps information about a variable in readable format. - * @param mixed variable to dump - * @return void - */ - private static function dump($var) - { - static $tableUtf, $tableBin, $reBinary = '#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u'; - if ($tableUtf === NULL) { - foreach (range("\x00", "\xFF") as $ch) { - if (ord($ch) < 32 && strpos("\r\n\t", $ch) === FALSE) { - $tableUtf[$ch] = $tableBin[$ch] = '\\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT); - } elseif (ord($ch) < 127) { - $tableUtf[$ch] = $tableBin[$ch] = $ch; - } else { - $tableUtf[$ch] = $ch; $tableBin[$ch] = '\\x' . dechex(ord($ch)); - } - } - $tableBin["\\"] = '\\\\'; - $tableBin["\r"] = '\\r'; - $tableBin["\n"] = '\\n'; - $tableBin["\t"] = '\\t'; - $tableUtf['\\x'] = $tableBin['\\x'] = '\\\\x'; - } - - if (is_bool($var)) { - return $var ? 'TRUE' : 'FALSE'; - - } elseif ($var === NULL) { - return 'NULL'; - - } elseif (is_int($var)) { - return "$var"; - - } elseif (is_float($var)) { - $var = var_export($var, TRUE); - return strpos($var, '.') === FALSE ? $var . '.0' : $var; - - } elseif (is_string($var)) { - if ($cut = @iconv_strlen($var, 'UTF-8') > 100) { - $var = iconv_substr($var, 0, 100, 'UTF-8'); - } elseif ($cut = strlen($var) > 100) { - $var = substr($var, 0, 100); - } - return '"' . strtr($var, preg_match($reBinary, $var) || preg_last_error() ? $tableBin : $tableUtf) . '"' . ($cut ? ' ...' : ''); - - } elseif (is_array($var)) { - return "array(" . count($var) . ")"; - - } elseif ($var instanceof Exception) { - return 'Exception ' . get_class($var) . ': ' . ($var->getCode() ? '#' . $var->getCode() . ' ' : '') . $var->getMessage(); - - } elseif (is_object($var)) { - $arr = (array) $var; - return "object(" . get_class($var) . ") (" . count($arr) . ")"; - - } elseif (is_resource($var)) { - return "resource(" . get_resource_type($var) . ")"; - - } else { - return "unknown type"; - } - } - - - - /** - * Dumps variable in PHP format. - * @param mixed variable to dump - * @return void - */ - private static function dumpPhp(&$var, $level = 0) - { - if (is_float($var)) { - $var = var_export($var, TRUE); - return strpos($var, '.') === FALSE ? $var . '.0' : $var; - - } elseif (is_bool($var)) { - return $var ? 'TRUE' : 'FALSE'; - - } elseif (is_string($var) && (preg_match('#[^\x09\x20-\x7E\xA0-\x{10FFFF}]#u', $var) || preg_last_error())) { - static $table; - if ($table === NULL) { - foreach (range("\x00", "\xFF") as $ch) { - $table[$ch] = ord($ch) < 32 || ord($ch) >= 127 - ? '\\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT) - : $ch; - } - $table["\r"] = '\r'; - $table["\n"] = '\n'; - $table["\t"] = '\t'; - $table['$'] = '\\$'; - $table['\\'] = '\\\\'; - $table['"'] = '\\"'; - } - return '"' . strtr($var, $table) . '"'; - - } elseif (is_array($var)) { - $s = ''; - $space = str_repeat("\t", $level); - - static $marker; - if ($marker === NULL) { - $marker = uniqid("\x00", TRUE); - } - if (empty($var)) { - - } elseif ($level > 50 || isset($var[$marker])) { - throw new \Exception('Nesting level too deep or recursive dependency.'); - - } else { - $s .= "\n"; - $var[$marker] = TRUE; - $counter = 0; - foreach ($var as $k => &$v) { - if ($k !== $marker) { - $s .= "$space\t" . ($k === $counter ? '' : self::dumpPhp($k) . " => ") . self::dumpPhp($v, $level + 1) . ",\n"; - $counter = is_int($k) ? max($k + 1, $counter) : $counter; - } - } - unset($var[$marker]); - $s .= $space; - } - return "array($s)"; - - } elseif (is_object($var)) { - $arr = (array) $var; - $s = ''; - $space = str_repeat("\t", $level); - - static $list = array(); - if (empty($arr)) { - - } elseif ($level > 50 || in_array($var, $list, TRUE)) { - throw new \Exception('Nesting level too deep or recursive dependency.'); - - } else { - $s .= "\n"; - $list[] = $var; - foreach ($arr as $k => &$v) { - if ($k[0] === "\x00") { - $k = substr($k, strrpos($k, "\x00") + 1); - } - $s .= "$space\t" . self::dumpPhp($k) . " => " . self::dumpPhp($v, $level + 1) . ",\n"; - } - array_pop($list); - $s .= $space; - } - return get_class($var) === 'stdClass' - ? "(object) array($s)" - : get_class($var) . "::__set_state(array($s))"; - - } else { - return var_export($var, TRUE); - } - } - - - - /** - * Logs big variables to file. - * @param mixed - * @param mixed - * @return void - */ - private static function log($expected, $actual) - { - $trace = debug_backtrace(); - $item = end($trace); - // in case of shutdown handler, we want to skip inner-code blocks - // and debugging calls (e.g. those of Nette\Diagnostics\Debugger) - // to get correct path to test file (which is the only purpose of this) - while (!isset($item['file']) || substr($item['file'], -5) !== '.phpt') { - $item = prev($trace); - if ($item === FALSE) { - return; - } - } - $file = dirname($item['file']) . '/output/' . basename($item['file'], '.phpt'); - - if (is_object($expected) || is_array($expected) || (is_string($expected) && strlen($expected) > 80)) { - @mkdir(dirname($file)); // @ - directory may already exist - file_put_contents($file . '.expected', is_string($expected) ? $expected : self::dumpPhp($expected)); - } - - if (is_object($actual) || is_array($actual) || (is_string($actual) && strlen($actual) > 80)) { - @mkdir(dirname($file)); // @ - directory may already exist - file_put_contents($file . '.actual', is_string($actual) ? $actual : self::dumpPhp($actual)); - } - } - -} diff --git a/tests/Test/RunTests.php b/tests/Test/RunTests.php deleted file mode 100644 index c072e49663..0000000000 --- a/tests/Test/RunTests.php +++ /dev/null @@ -1,51 +0,0 @@ - -Nette Test Framework (v0.4) ---------------------------- - -Usage: - php RunTests.php [options] [file or directory] - -Options: - -p Specify PHP-CGI executable to run. - -c Look for php.ini in directory or use as php.ini. - -log Write log to file . - -d key=val Define INI entry 'key' with value 'val'. - -s Show information about skipped tests. - -j Run jobs in parallel. - -parseArguments(); - $res = $manager->run(); - die($res ? 0 : 1); - -} catch (Exception $e) { - echo 'Error: ', $e->getMessage(), "\n"; - die(2); -} diff --git a/tests/Test/TestCase.php b/tests/Test/TestCase.php deleted file mode 100644 index ce392f5b66..0000000000 --- a/tests/Test/TestCase.php +++ /dev/null @@ -1,334 +0,0 @@ -file = (string) $testFile; - $this->args = $args; - $this->options = self::parseOptions($this->file); - } - - - - /** - * Runs single test. - * @param bool - * @return TestCase provides a fluent interface - */ - public function run($blocking = true) - { - // pre-skip? - if (isset($this->options['skip'])) { - $message = $this->options['skip'] ? $this->options['skip'] : 'No message.'; - throw new TestCaseException($message, TestCaseException::SKIPPED); - - } elseif (isset($this->options['phpversion'])) { - $operator = '>='; - if (preg_match('#^(<=|le|<|lt|==|=|eq|!=|<>|ne|>=|ge|>|gt)#', $this->options['phpversion'], $matches)) { - $this->options['phpversion'] = trim(substr($this->options['phpversion'], strlen($matches[1]))); - $operator = $matches[1]; - } - if (version_compare($this->options['phpversion'], $this->phpVersion, $operator)) { - throw new TestCaseException("Requires PHP $operator {$this->options['phpversion']}.", TestCaseException::SKIPPED); - } - } - - $this->execute($blocking); - return $this; - } - - - - /** - * Sets PHP command line. - * @param string - * @param string - * @return TestCase provides a fluent interface - */ - public function setPhp($binary, $args) - { - if (isset(self::$cachedPhp[$binary])) { - list($this->phpVersion, $this->phpType) = self::$cachedPhp[$binary]; - - } else { - exec(escapeshellarg($binary) . ' -v', $output, $res); - if ($res !== self::CODE_OK && $res !== self::CODE_ERROR) { - throw new Exception("Unable to execute '$binary -v'."); - } - - if (!preg_match('#^PHP (\S+).*c(g|l)i#i', $output[0], $matches)) { - throw new Exception("Unable to detect PHP version (output: $output[0])."); - } - - $this->phpVersion = $matches[1]; - $this->phpType = strcasecmp($matches[2], 'g') ? 'CLI' : 'CGI'; - self::$cachedPhp[$binary] = array($this->phpVersion, $this->phpType); - } - - $this->cmdLine = escapeshellarg($binary) . $args; - return $this; - } - - - - /** - * Execute test. - * @param bool - * @return void - */ - private function execute($blocking) - { - $this->headers = $this->output = NULL; - - if (isset($this->options['phpini'])) { - foreach (explode(';', $this->options['phpini']) as $item) { - $this->cmdLine .= " -d " . escapeshellarg(trim($item)); - } - } - $this->cmdLine .= ' ' . escapeshellarg($this->file) . ' ' . $this->args; - - $descriptors = array( - array('pipe', 'r'), - array('pipe', 'w'), - array('pipe', 'w'), - ); - - $this->proc = proc_open($this->cmdLine, $descriptors, $pipes, dirname($this->file), null, array('bypass_shell' => true)); - list($stdin, $this->stdout, $stderr) = $pipes; - fclose($stdin); - stream_set_blocking($this->stdout, $blocking ? 1 : 0); - fclose($stderr); - } - - - - /** - * Checks if the test results are ready. - * @return bool - */ - public function isReady() - { - $this->output .= stream_get_contents($this->stdout); - $status = proc_get_status($this->proc); - if ($status['exitcode'] !== self::CODE_NONE) { - $this->exitCode = $status['exitcode']; - } - return !$status['running']; - } - - - - /** - * Collect results. - * @return void - */ - public function collect() - { - $this->output .= stream_get_contents($this->stdout); - fclose($this->stdout); - $res = proc_close($this->proc); - if ($res === self::CODE_NONE) { - $res = $this->exitCode; - } - - if ($this->phpType === 'CGI') { - list($headers, $this->output) = explode("\r\n\r\n", $this->output, 2); - } else { - $headers = ''; - } - - $this->headers = array(); - foreach (explode("\r\n", $headers) as $header) { - $a = strpos($header, ':'); - if ($a !== FALSE) { - $this->headers[trim(substr($header, 0, $a))] = (string) trim(substr($header, $a + 1)); - } - } - - if ($res === self::CODE_ERROR) { - throw new TestCaseException($this->output ?: 'Fatal error'); - - } elseif ($res === self::CODE_FAIL) { - throw new TestCaseException($this->output); - - } elseif ($res === self::CODE_SKIP) { // skip - throw new TestCaseException($this->output, TestCaseException::SKIPPED); - - } elseif ($res !== self::CODE_OK) { - throw new Exception("Unable to execute '$this->cmdLine'."); - - } - - // HTTP code check - if (isset($this->options['assertcode'])) { - $code = isset($this->headers['Status']) ? (int) $this->headers['Status'] : 200; - if ($code !== (int) $this->options['assertcode']) { - throw new TestCaseException('Expected HTTP code ' . $this->options['assertcode'] . ' is not same as actual code ' . $code); - } - } - } - - - - /** - * Returns test file path. - * @return string - */ - public function getFile() - { - return $this->file; - } - - - - /** - * Returns test name. - * @return string - */ - public function getName() - { - return $this->options['name']; - } - - - - /** - * Returns test args. - * @return string - */ - public function getArguments() - { - return $this->args; - } - - - - /** - * Returns test output. - * @return string - */ - public function getOutput() - { - return $this->output; - } - - - - /** - * Returns output headers. - * @return string - */ - public function getHeaders() - { - return $this->headers; - } - - - - /********************* helpers ****************d*g**/ - - - - /** - * Parse phpDoc. - * @param string file - * @return array - */ - public static function parseOptions($testFile) - { - $content = file_get_contents($testFile); - $options = array(); - $phpDoc = preg_match('#^/\*\*(.*?)\*/#ms', $content, $matches) ? trim($matches[1]) : ''; - preg_match_all('#^\s*\*\s*@(\S+)(.*)#mi', $phpDoc, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $options[strtolower($match[1])] = isset($match[2]) ? trim($match[2]) : TRUE; - } - $options['name'] = preg_match('#^\s*\*\s*TEST:(.*)#mi', $phpDoc, $matches) ? trim($matches[1]) : $testFile; - return $options; - } - -} - - - -/** - * Single test exception. - * - * @author David Grudl - * @package Nette\Test - */ -class TestCaseException extends Exception -{ - const SKIPPED = 1; - -} diff --git a/tests/Test/TestHelpers.php b/tests/Test/TestHelpers.php deleted file mode 100644 index 102885c65a..0000000000 --- a/tests/Test/TestHelpers.php +++ /dev/null @@ -1,158 +0,0 @@ -getBasename(), 0, 1) === '.') { // . or .. or .gitignore - // ignore - } elseif ($entry->isDir()) { - rmdir($entry); - } else { - unlink($entry); - } - } - } - - - - /** - * Log info. - * @return void - */ - public static function note($message) - { - self::$notes[] = $message; - } - - - - /** - * Returns notes. - * @return array - */ - public static function fetchNotes() - { - $res = self::$notes; - self::$notes = array(); - return $res; - } - - - - /** - * Skips this test. - * @return void - */ - public static function skip($message = '') - { - echo "\nSkipped:\n$message\n"; - die(TestCase::CODE_SKIP); - } - - - - /** - * locks the parallel tests. - * @return void - */ - public static function lock($name = '', $path = '') - { - static $lock; - flock($lock = fopen($path . '/lock-' . md5($name), 'w'), LOCK_EX); - } - - - - /** - * Starts gathering the information for code coverage. - * @param string - * @return void - */ - public static function startCodeCoverage($file) - { - self::$coverageFile = $file; - xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); - register_shutdown_function(array(__CLASS__, 'prepareSaveCoverage')); - } - - - - /** - * Coverage saving helper. Do not call directly. - * @return void - * @internal - */ - public static function prepareSaveCoverage() - { - register_shutdown_function(array(__CLASS__, 'saveCoverage')); - } - - - - /** - * Saves information about code coverage. Do not call directly. - * @return void - * @internal - */ - public static function saveCoverage() - { - $f = fopen(self::$coverageFile, 'a+'); - flock($f, LOCK_EX); - fseek($f, 0); - $coverage = @unserialize(stream_get_contents($f)); - $root = realpath(__DIR__ . '/../../Nette') . DIRECTORY_SEPARATOR; - - foreach (xdebug_get_code_coverage() as $filename => $lines) { - if (strncmp($root, $filename, strlen($root))) { - continue; - } - - foreach ($lines as $num => $val) { - if (empty($coverage[$filename][$num]) || $val > 0) { - $coverage[$filename][$num] = $val; // -1 => untested; -2 => dead code - } - } - } - - ftruncate($f, 0); - fwrite($f, serialize($coverage)); - fclose($f); - } - -} diff --git a/tests/Test/TestRunner.php b/tests/Test/TestRunner.php deleted file mode 100644 index c09b8ebde4..0000000000 --- a/tests/Test/TestRunner.php +++ /dev/null @@ -1,260 +0,0 @@ -phpBinary) . ' -v', $output); - if (!isset($output[0])) { - return FALSE; - - } elseif (strpos($output[0], 'cgi-fcgi') === FALSE) { - echo "Nette Framework Tests suite requires php-cgi, " . $this->phpBinary . " given.\n\n"; - return FALSE; - } - echo $this->log("$output[0] | $this->phpBinary $this->phpArgs\n"); - - $tests = array(); - foreach ($this->paths as $path) { - if (is_file($path)) { - $files = array($path); - } else { - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - } - foreach ($files as $file) { - $file = (string) $file; - $info = pathinfo($file); - if (!isset($info['extension']) || $info['extension'] !== 'phpt') { - continue; - } - - $options = TestCase::parseOptions($file); - if (!empty($options['multiple'])) { - if (is_numeric($options['multiple'])) { - $range = range(0, $options['multiple'] - 1); - - } elseif (!is_file($multiFile = dirname($file) . '/' . $options['multiple'])) { - throw new Exception("Missing @multiple configuration file '$multiFile'."); - - } elseif (($multiple = parse_ini_file($multiFile, TRUE)) === FALSE) { - throw new Exception("Cannot parse @multiple configuration file '$multiFile'."); - - } else { - $range = array_keys($multiple); - } - foreach ($range as $item) { - $tests[] = array($file, escapeshellarg($item)); - } - - } else { - $tests[] = array($file, NULL); - } - } - } - - $running = array(); - while ($tests || $running) { - for ($i = count($running); $tests && $i < $this->jobs; $i++) { - list($file, $args) = array_shift($tests); - $count++; - $testCase = new TestCase($file, $args); - $testCase->setPhp($this->phpBinary, $this->phpArgs); - try { - $parallel = ($this->jobs > 1) && (count($running) + count($tests) > 1); - $running[] = $testCase->run(!$parallel); - } catch (TestCaseException $e) { - echo 's'; - $skipped[] = $this->log($this->format('Skipped', $testCase, $e)); - } - } - if (count($running) > 1) { - usleep(self::RUN_USLEEP); // stream_select() doesn't work with proc_open() - } - foreach ($running as $key => $testCase) { - if ($testCase->isReady()) { - try { - $testCase->collect(); - echo '.'; - $passed[] = array($testCase->getName(), $testCase->getFile()); - - } catch (TestCaseException $e) { - if ($e->getCode() === TestCaseException::SKIPPED) { - echo 's'; - $skipped[] = $this->log($this->format('Skipped', $testCase, $e)); - - } else { - echo 'F'; - $failed[] = $this->log($this->format('FAILED', $testCase, $e)); - } - } - unset($running[$key]); - } - } - } - - $failedCount = count($failed); - $skippedCount = count($skipped); - - if ($this->displaySkipped) { - echo "\n", implode($skipped); - } - - if (!$count) { - echo $this->log("No tests found\n"); - - } elseif ($failedCount) { - echo "\n", implode($failed); - echo $this->log("\nFAILURES! ($count tests, $failedCount failures, $skippedCount skipped)"); - return FALSE; - - } else { - echo $this->log("\n\nOK ($count tests, $skippedCount skipped)"); - } - return TRUE; - } - - - - /** - * Parses command line arguments. - * @return void - */ - public function parseArguments() - { - $this->phpBinary = 'php-cgi'; - $this->phpArgs = ''; - $this->paths = array(); - $iniSet = FALSE; - - $args = new ArrayIterator(array_slice(isset($_SERVER['argv']) ? $_SERVER['argv'] : array(), 1)); - foreach ($args as $arg) { - if (!preg_match('#^[-/][a-z]+$#', $arg)) { - if ($path = realpath($arg)) { - $this->paths[] = $path; - } else { - throw new Exception("Invalid path '$arg'."); - } - - } else switch (substr($arg, 1)) { - case 'p': - $args->next(); - $this->phpBinary = $args->current(); - break; - case 'log': - $args->next(); - $this->logFile = fopen($file = $args->current(), 'w'); - echo "Log: $file\n"; - break; - case 'c': - $args->next(); - $path = realpath($args->current()); - if ($path === FALSE) { - throw new Exception("PHP configuration file '{$args->current()}' not found."); - } - $this->phpArgs .= " -c " . escapeshellarg($path); - $iniSet = TRUE; - break; - case 'd': - $args->next(); - $this->phpArgs .= " -d " . escapeshellarg($args->current()); - break; - case 's': - $this->displaySkipped = TRUE; - break; - case 'j': - $args->next(); - $this->jobs = max(1, (int) $args->current()); - break; - default: - throw new Exception("Unknown option $arg."); - exit; - } - } - - if (!$this->paths) { - $this->paths[] = getcwd(); // current directory - } - if (!$iniSet) { - $this->phpArgs .= " -n"; - } - } - - - - /** - * Writes to log - * @return string - */ - private function log($s) - { - if ($this->logFile) { - fputs($this->logFile, "$s\n"); - } - return "$s\n"; - } - - - - /** - * @return string - */ - private function format($s, $testCase, $e) - { - return "\n-- $s: {$testCase->getName()}" - . ($testCase->getArguments() ? " [{$testCase->getArguments()}]" : '') . ' | ' - . implode(DIRECTORY_SEPARATOR, array_slice(explode(DIRECTORY_SEPARATOR, $testCase->getFile()), -3)) - . str_replace("\n", "\n ", "\n" . trim($e->getMessage())) . "\n"; - } - -} diff --git a/tests/Test/ViewCoverage.php b/tests/Test/ViewCoverage.php deleted file mode 100644 index 45035c04d9..0000000000 --- a/tests/Test/ViewCoverage.php +++ /dev/null @@ -1,237 +0,0 @@ -getBasename(), 0, 1) === '.') { // . or .. or .gitignore - continue; - } - $entry = (string) $entry; - - $coverage = $covered = $total = 0; - $lines = array(); - if (isset($coverageInfo[$entry])) { - $lines = $coverageInfo[$entry]; - foreach ($lines as $flag) { - if ($flag >= -1) { - $total++; - } - if ($flag >= 1) { - $covered++; - } - } - $coverage = round($covered * 100 / $total); - $totalSum += $total; - $coveredSum += $covered; - } - - $files[] = (object) array( - 'name' => str_replace($root, '', $entry), - 'file' => $entry, - 'lines' => $lines, - 'coverage' => $coverage, - 'total' => $total, - 'light' => $total ? $total < 5 : count(file($entry)) < 50, - ); -} - - - -$classes = array( - 1 => 't', // tested - -1 => 'u', // untested - -2 => 'dead', // dead code -); - -ini_set('highlight.comment', '#999; font-style: italic'); -ini_set('highlight.default', '#000'); -ini_set('highlight.html', '#06B'); -ini_set('highlight.keyword', '#D24; font-weight: bold'); -ini_set('highlight.string', '#080'); - -?> - - - - - - - - Nette Framework code coverage - - - - - - - -

Nette Framework Code coverage  %

- - $info): ?> -
- - light ? 'class="light"' : '' ?>> - - - - -
coverage ?> %
name ?>
- -
- ', highlight_file($info->file, TRUE)); - - end($source); - $numWidth = strlen((string) key($source)); - - unset($prevColor); - $tags = ''; - foreach ($source as $n => $line) { - if (isset($info->lines[$n + 1]) && isset($classes[$info->lines[$n + 1]])) { - $color = $classes[$info->lines[$n + 1]]; - } else { - $color = ''; // not executable - } - if (!isset($prevColor)) { - $prevColor = $color; - } - $line = sprintf("%{$numWidth}s: ", $n + 1) . $line; - if ($prevColor !== $color || $n === count($source) - 1) { - echo '', str_replace(' />', '>', $tags); - $openTags = array(); - preg_match_all('#<([^>]+)#', $tags, $matches); - foreach ($matches[1] as $m) { - if ($m[0] === '/') { - array_pop($openTags); - } elseif (substr($m, -1) !== '/') { - $openTags[] = $m; - } - } - foreach (array_reverse($openTags) as $tag) { - echo ''; - } - echo "
\n"; - $tags = ($openTags ? '<' . implode('><', $openTags) . '>' : ''); - $prevColor = $color; - } - $tags .= "$line
\n"; - } - ?>
- - - - - - diff --git a/tests/run-tests.sh b/tests/run-tests.sh index 15b6c9fbc3..accffaf5f8 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -22,9 +22,9 @@ done # runs RunTests.php with script's arguments, add default php.ini if not specified if [ -n "$PhpIni" ]; then - php -c "$PhpIni" "$dir/Test/RunTests.php" "$@" + php -c "$PhpIni" "$dir/../vendor/nette/tester/Tester/RunTests.phpc" "$@" else - php -c "$dir/php.ini-unix" "$dir/Test/RunTests.php" -c "$dir/php.ini-unix" "$@" + php -c "$dir/php.ini-unix" "$dir/../vendor/nette/tester/Tester/RunTests.phpc" -c "$dir/php.ini-unix" "$@" fi error=$?