/** * Returns the methods of the class under test * that are called from the test methods. * * @return array */ protected function findTestedMethods() { $setUpVariables = array(); $testedMethods = array(); $classes = PHPUnit_Util_File::getClassesInFile($this->inSourceFile); $testMethods = $classes[$this->inClassName['fullyQualifiedClassName']]['methods']; unset($classes); foreach ($testMethods as $name => $testMethod) { if (strtolower($name) == 'setup') { $setUpVariables = $this->findVariablesThatReferenceClass($testMethod['tokens']); break; } } foreach ($testMethods as $name => $testMethod) { $argVariables = array(); if (strtolower($name) == 'setup') { continue; } $start = strpos($testMethod['signature'], '(') + 1; $end = strlen($testMethod['signature']) - $start - 1; $args = substr($testMethod['signature'], $start, $end); foreach (explode(',', $args) as $arg) { $arg = explode(' ', trim($arg)); if (count($arg) == 2) { $type = $arg[0]; $var = $arg[1]; } else { $type = NULL; $var = $arg[0]; } if ($type == $this->outClassName['fullyQualifiedClassName']) { $argVariables[] = $var; } } $variables = array_unique(array_merge($setUpVariables, $argVariables, $this->findVariablesThatReferenceClass($testMethod['tokens']))); foreach ($testMethod['tokens'] as $i => $token) { // Class::method() if (is_array($token) && $token[0] == T_DOUBLE_COLON && is_array($testMethod['tokens'][$i - 1]) && $testMethod['tokens'][$i - 1][0] == T_STRING && $testMethod['tokens'][$i - 1][1] == $this->outClassName['fullyQualifiedClassName'] && is_array($testMethod['tokens'][$i + 1]) && $testMethod['tokens'][$i + 1][0] == T_STRING && $testMethod['tokens'][$i + 2] == '(') { $testedMethods[] = $testMethod['tokens'][$i + 1][1]; } else { if (is_array($token) && $token[0] == T_OBJECT_OPERATOR && in_array($this->findVariableName($testMethod['tokens'], $i), $variables) && is_array($testMethod['tokens'][$i + 2]) && $testMethod['tokens'][$i + 2][0] == T_OBJECT_OPERATOR && is_array($testMethod['tokens'][$i + 3]) && $testMethod['tokens'][$i + 3][0] == T_STRING && $testMethod['tokens'][$i + 4] == '(') { $testedMethods[] = $testMethod['tokens'][$i + 3][1]; } else { if (is_array($token) && $token[0] == T_OBJECT_OPERATOR && in_array($this->findVariableName($testMethod['tokens'], $i), $variables) && is_array($testMethod['tokens'][$i + 1]) && $testMethod['tokens'][$i + 1][0] == T_STRING && $testMethod['tokens'][$i + 2] == '(') { $testedMethods[] = $testMethod['tokens'][$i + 1][1]; } } } } } $testedMethods = array_unique($testedMethods); sort($testedMethods); return $testedMethods; }
protected function processFunctions() { $functions = PHPUnit_Util_File::getFunctionsInFile($this->getPath()); if (count($functions) > 0 && !isset($this->classes['*'])) { $this->classes['*'] = array('methods' => array(), 'startLine' => 0, 'executableLines' => 0, 'executedLines' => 0); } foreach ($functions as $functionName => $function) { $this->classes['*']['methods'][$functionName] = array('signature' => $function['signature'], 'startLine' => $function['startLine'], 'executableLines' => 0, 'executedLines' => 0); $this->startLines[$function['startLine']] =& $this->classes['*']['methods'][$functionName]; $this->endLines[$function['endLine']] =& $this->classes['*']['methods'][$functionName]; $this->numMethods++; } }
#!/usr/bin/env php <?php if ($argc < 2) { die("Usage {$argv[0]} FILE [OUTPUT_DIR]"); } set_include_path(__DIR__ . '/../../src/' . PATH_SEPARATOR . get_include_path()); require 'phpMorphy.php'; require 'PHPUnit/Util/File.php'; define('DEFAULT_TESTS_DIR', PHPMORPHY_DIR . '/../tests'); $phpunit_bin = '/usr/bin/env phpunit'; $phpunit_args = '--bootstrap ' . escapeshellarg(DEFAULT_TESTS_DIR . '/bootstrap.php'); $remove_class_prefix = 'phpMorphy_'; $input_file = (string) $argv[1]; $output_dir = $argc > 2 ? (string) $argv[2] : DEFAULT_TESTS_DIR . '/unit'; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// $output_dir = realpath($output_dir); $output_dir = rtrim($output_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $classes = PHPUnit_Util_File::getClassesInFile($input_file); foreach ($classes as $class_name => $class_descriptor) { echo "==> Generate test for {$class_name} class\n"; $stripped_class_name = substr($class_name, strlen($remove_class_prefix)); $test_class_path = phpMorphy_Loader::classNameToFilePath($stripped_class_name); $test_file_path = $output_dir . preg_replace('/\\.php$/u', '', $test_class_path) . 'Test.php'; $test_class_name = 'test_' . $stripped_class_name; $args = array('--skeleton-test', $class_name, $input_file, $test_class_name, $test_file_path); $cmd = $phpunit_bin . ' ' . ('' !== $phpunit_args ? $phpunit_args . ' ' : '') . implode(' ', array_map('escapeshellarg', $args)); @mkdir(dirname($test_file_path)); passthru($cmd); }
/** * Constructor. * * @param string $filename * @param array $codeCoverage * @throws RuntimeException */ protected function __construct($filename, &$codeCoverage = array()) { if (!file_exists($filename)) { throw new RuntimeException(sprintf('File "%s" not found.', $filename)); } $this->filename = $filename; foreach (PHPUnit_Util_File::countLines($this->filename) as $name => $value) { $this->{$name} = $value; } $this->setCoverage($codeCoverage); foreach (PHPUnit_Util_File::getClassesInFile($filename) as $className => $class) { $this->classes[$className] = PHPUnit_Util_Metrics_Class::factory(new ReflectionClass($className), $codeCoverage); } foreach (PHPUnit_Util_File::getFunctionsInFile($filename) as $functionName => $function) { $this->functions[$functionName] = PHPUnit_Util_Metrics_Function::factory(new ReflectionFunction($functionName), $codeCoverage); } }
protected function _getClassessInFile($path) { if (version_compare(PHPUnit_Runner_Version::id(), '3.4', '<')) { $classes = array(); foreach (PHPUnit_Util_Class::getClassesInFile($path) as $reflection) { $classes[] = $reflection->getName(); } return $classes; } else { return array_keys(PHPUnit_Util_File::getClassesInFile($path)); } }
/** * @param PHPUnit_Framework_TestResult $result * @todo Count conditionals. */ public function process(PHPUnit_Framework_TestResult $result) { $time = time(); $document = new DOMDocument('1.0', 'UTF-8'); $document->formatOutput = TRUE; $coverage = $document->createElement('coverage'); $coverage->setAttribute('generated', $time); $coverage->setAttribute('phpunit', PHPUnit_Runner_Version::id()); $document->appendChild($coverage); $project = $document->createElement('project'); $project->setAttribute('name', $result->topTestSuite()->getName()); $project->setAttribute('timestamp', $time); $coverage->appendChild($project); $codeCoverageInformation = $result->getCodeCoverageInformation(); $files = PHPUnit_Util_CodeCoverage::getSummary($codeCoverageInformation); $packages = array(); $projectStatistics = array('files' => 0, 'loc' => 0, 'ncloc' => 0, 'classes' => 0, 'methods' => 0, 'coveredMethods' => 0, 'conditionals' => 0, 'coveredConditionals' => 0, 'statements' => 0, 'coveredStatements' => 0); foreach ($files as $filename => $data) { $namespace = 'global'; if (file_exists($filename)) { $fileStatistics = array('classes' => 0, 'methods' => 0, 'coveredMethods' => 0, 'conditionals' => 0, 'coveredConditionals' => 0, 'statements' => 0, 'coveredStatements' => 0); $file = $document->createElement('file'); $file->setAttribute('name', $filename); $classesInFile = PHPUnit_Util_File::getClassesInFile($filename); $lines = array(); foreach ($classesInFile as $className => $_class) { $classStatistics = array('methods' => 0, 'coveredMethods' => 0, 'conditionals' => 0, 'coveredConditionals' => 0, 'statements' => 0, 'coveredStatements' => 0); foreach ($_class['methods'] as $methodName => $method) { $classStatistics['methods']++; $methodCount = 0; for ($i = $method['startLine']; $i <= $method['endLine']; $i++) { $add = TRUE; $count = 0; if (isset($files[$filename][$i])) { if ($files[$filename][$i] != -2) { $classStatistics['statements']++; } if (is_array($files[$filename][$i])) { $classStatistics['coveredStatements']++; $count = count($files[$filename][$i]); } else { if ($files[$filename][$i] == -2) { $add = FALSE; } } } else { $add = FALSE; } $methodCount = max($methodCount, $count); if ($add) { $lines[$i] = array('count' => $count, 'type' => 'stmt'); } } if ($methodCount > 0) { $classStatistics['coveredMethods']++; } $lines[$method['startLine']] = array('count' => $methodCount, 'type' => 'method', 'name' => $methodName); } $packageInformation = PHPUnit_Util_Class::getPackageInformation($className, $_class['docComment']); if (!empty($packageInformation['namespace'])) { $namespace = $packageInformation['namespace']; } $class = $document->createElement('class'); $class->setAttribute('name', $className); $class->setAttribute('namespace', $namespace); if (!empty($packageInformation['fullPackage'])) { $class->setAttribute('fullPackage', $packageInformation['fullPackage']); } if (!empty($packageInformation['category'])) { $class->setAttribute('category', $packageInformation['category']); } if (!empty($packageInformation['package'])) { $class->setAttribute('package', $packageInformation['package']); } if (!empty($packageInformation['subpackage'])) { $class->setAttribute('subpackage', $packageInformation['subpackage']); } $file->appendChild($class); $metrics = $document->createElement('metrics'); $metrics->setAttribute('methods', $classStatistics['methods']); $metrics->setAttribute('coveredmethods', $classStatistics['coveredMethods']); //$metrics->setAttribute('conditionals', $classStatistics['conditionals']); //$metrics->setAttribute('coveredconditionals', $classStatistics['coveredConditionals']); $metrics->setAttribute('statements', $classStatistics['statements']); $metrics->setAttribute('coveredstatements', $classStatistics['coveredStatements']); $metrics->setAttribute('elements', $classStatistics['conditionals'] + $classStatistics['statements'] + $classStatistics['methods']); $metrics->setAttribute('coveredelements', $classStatistics['coveredConditionals'] + $classStatistics['coveredStatements'] + $classStatistics['coveredMethods']); $class->appendChild($metrics); $fileStatistics['methods'] += $classStatistics['methods']; $fileStatistics['coveredMethods'] += $classStatistics['coveredMethods']; $fileStatistics['conditionals'] += $classStatistics['conditionals']; $fileStatistics['coveredConditionals'] += $classStatistics['coveredConditionals']; $fileStatistics['statements'] += $classStatistics['statements']; $fileStatistics['coveredStatements'] += $classStatistics['coveredStatements']; $fileStatistics['classes']++; } foreach ($data as $_line => $_data) { if (isset($lines[$_line])) { continue; } if ($_data != -2) { $fileStatistics['statements']++; if (is_array($_data)) { $count = count($_data); $fileStatistics['coveredStatements']++; } else { $count = 0; } $lines[$_line] = array('count' => $count, 'type' => 'stmt'); } } ksort($lines); foreach ($lines as $_line => $_data) { $line = $document->createElement('line'); $line->setAttribute('num', $_line); $line->setAttribute('type', $_data['type']); if (isset($_data['name'])) { $line->setAttribute('name', $_data['name']); } $line->setAttribute('count', $_data['count']); $file->appendChild($line); } $count = PHPUnit_Util_File::countLines($filename); $metrics = $document->createElement('metrics'); $metrics->setAttribute('loc', $count['loc']); $metrics->setAttribute('ncloc', $count['ncloc']); $metrics->setAttribute('classes', $fileStatistics['classes']); $metrics->setAttribute('methods', $fileStatistics['methods']); $metrics->setAttribute('coveredmethods', $fileStatistics['coveredMethods']); //$metrics->setAttribute('conditionals', $fileStatistics['conditionals']); //$metrics->setAttribute('coveredconditionals', $fileStatistics['coveredConditionals']); $metrics->setAttribute('statements', $fileStatistics['statements']); $metrics->setAttribute('coveredstatements', $fileStatistics['coveredStatements']); $metrics->setAttribute('elements', $fileStatistics['conditionals'] + $fileStatistics['statements'] + $fileStatistics['methods']); $metrics->setAttribute('coveredelements', $fileStatistics['coveredConditionals'] + $fileStatistics['coveredStatements'] + $fileStatistics['coveredMethods']); $file->appendChild($metrics); if ($namespace == 'global') { $project->appendChild($file); } else { if (!isset($packages[$namespace])) { $packages[$namespace] = $document->createElement('package'); $packages[$namespace]->setAttribute('name', $namespace); $project->appendChild($packages[$namespace]); } $packages[$namespace]->appendChild($file); } $projectStatistics['loc'] += $count['loc']; $projectStatistics['ncloc'] += $count['ncloc']; $projectStatistics['classes'] += $fileStatistics['classes']; $projectStatistics['methods'] += $fileStatistics['methods']; $projectStatistics['coveredMethods'] += $fileStatistics['coveredMethods']; $projectStatistics['conditionals'] += $fileStatistics['conditionals']; $projectStatistics['coveredConditionals'] += $fileStatistics['coveredConditionals']; $projectStatistics['statements'] += $fileStatistics['statements']; $projectStatistics['coveredStatements'] += $fileStatistics['coveredStatements']; $projectStatistics['files']++; } } $metrics = $document->createElement('metrics'); $metrics->setAttribute('files', $projectStatistics['files']); $metrics->setAttribute('loc', $projectStatistics['loc']); $metrics->setAttribute('ncloc', $projectStatistics['ncloc']); $metrics->setAttribute('classes', $projectStatistics['classes']); $metrics->setAttribute('methods', $projectStatistics['methods']); $metrics->setAttribute('coveredmethods', $projectStatistics['coveredMethods']); //$metrics->setAttribute('conditionals', $projectStatistics['conditionals']); //$metrics->setAttribute('coveredconditionals', $projectStatistics['coveredConditionals']); $metrics->setAttribute('statements', $projectStatistics['statements']); $metrics->setAttribute('coveredstatements', $projectStatistics['coveredStatements']); $metrics->setAttribute('elements', $projectStatistics['conditionals'] + $projectStatistics['statements'] + $projectStatistics['methods']); $metrics->setAttribute('coveredelements', $projectStatistics['coveredConditionals'] + $projectStatistics['coveredStatements'] + $projectStatistics['coveredMethods']); $project->appendChild($metrics); $this->write($document->saveXML()); $this->flush(); }