public function testFormaterReturnsXml() { // all results $rs1 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $rs1->expects($this->any())->method('asArray')->will($this->returnValue(array('volume' => 5))); $rs1->expects($this->any())->method('getFilename')->will($this->returnValue('path2/file1.php')); $rs2 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $rs2->expects($this->any())->method('asArray')->will($this->returnValue(array('volume' => 15))); $rs2->expects($this->any())->method('getFilename')->will($this->returnValue('path1/file1.php')); $collection = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultCollection')->disableOriginalConstructor()->getMock(); $collection->expects($this->any())->method('getIterator')->will($this->returnValue(new \ArrayIterator(array($rs1, $rs2)))); $collection->expects($this->any())->method('getFilename')->will($this->returnValue('abc')); $collection->expects($this->any())->method('asArray')->will($this->returnValue(array(array('volume' => 5), array('volume' => 15)))); $bounds = new Bounds(); // grouped results $groupedResults = new ResultCollection(); $result = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultAggregate')->disableOriginalConstructor()->getMock(); $result->expects($this->any())->method('getName')->will($this->returnValue('path1')); $result->expects($this->any())->method('getBounds')->will($this->returnValue($this->getMock('\\Hal\\Component\\Bounds\\Result\\ResultInterface'))); $groupedResults->push($result); $result = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultAggregate')->disableOriginalConstructor()->getMock(); $result->expects($this->any())->method('getName')->will($this->returnValue('path2')); $result->expects($this->any())->method('getBounds')->will($this->returnValue($this->getMock('\\Hal\\Component\\Bounds\\Result\\ResultInterface'))); $groupedResults->push($result); // formater $validator = $this->getMockBuilder('\\Hal\\Application\\Rule\\Validator')->disableOriginalConstructor()->getMock(); $formater = new Xml($validator, $bounds, $this->getMockBuilder('\\Hal\\Application\\Extension\\ExtensionService')->disableOriginalConstructor()->getMock()); $output = $formater->terminate($collection, $groupedResults); $xml = new \SimpleXMLElement($output); $p = $xml->xpath('//project'); $this->assertEquals('10', $p[0]['volume']); $m = $xml->xpath('//project/modules/module[@namespace="path1"]'); $m = $m[0]; $this->assertCount(2, $xml->xpath('//project/modules/module')); }
public function testICanAggregatesResults() { $collection = new ResultCollection(); $collection->push(new ResultSet(str_replace('/', DIRECTORY_SEPARATOR, '/root1/folder1/file1.php'))); $collection->push(new ResultSet(str_replace('/', DIRECTORY_SEPARATOR, '/root1/folder1/file2.php'))); $collection->push(new ResultSet(str_replace('/', DIRECTORY_SEPARATOR, '/root1/folder1/file3.php'))); $collection->push(new ResultSet(str_replace('/', DIRECTORY_SEPARATOR, '/root1/folder2/file1.php'))); $collection->push(new ResultSet(str_replace('/', DIRECTORY_SEPARATOR, '/root2/file1.php'))); $aggregator = new DirectoryRecursiveAggregator(0); $results = $aggregator->aggregates($collection); $this->assertArrayHasKey('.', $results); $results = $results['.']; $this->assertEquals(2, sizeof($results, COUNT_NORMAL), 'root'); $this->assertArrayHasKey('root1', $results); $this->assertEquals(2, sizeof($results['root1'], COUNT_NORMAL), 'first level'); $this->assertArrayHasKey('folder1', $results['root1']); $this->assertEquals(3, sizeof($results['root1']['folder1'], COUNT_NORMAL), 'second level'); $this->assertEquals(1, sizeof($results['root1']['folder2'], COUNT_NORMAL), 'second level B'); $this->assertEquals(1, sizeof($results['root2'], COUNT_NORMAL), 'fist level B'); }
/** * @dataProvider provideAbstractness */ public function testICanKnowTheAbstractnessOfPackage($expected, $abstractClasses, $concreteClasses) { $instability = new Abstractness(); $results = new ResultCollection(); $oop = $this->getMockBuilder('\\Hal\\Component\\OOP\\Extractor\\Result')->disableOriginalConstructor()->getMock(); $oop->expects($this->any())->method('getConcreteClasses')->will($this->returnValue(array_pad(array(), $concreteClasses, null))); $oop->expects($this->any())->method('getAbstractClasses')->will($this->returnValue(array_pad(array(), $abstractClasses, null))); $resultSet = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $resultSet->expects($this->any())->method('getOOP')->will($this->returnValue($oop)); $results->push($resultSet); $r = $instability->calculate($results); $this->assertEquals($expected, $r->getAbstractness()); }
public function testFormaterReturnsXml() { // all results $rs1 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $rs1->expects($this->any())->method('asArray')->will($this->returnValue(array('loc' => 5))); $rs1->expects($this->any())->method('getFilename')->will($this->returnValue('path2/file1.php')); $rs2 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $rs2->expects($this->any())->method('asArray')->will($this->returnValue(array('loc' => 15))); $rs2->expects($this->any())->method('getFilename')->will($this->returnValue('path1/file1.php')); $collection = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultCollection')->disableOriginalConstructor()->getMock(); $collection->expects($this->any())->method('getIterator')->will($this->returnValue(new \ArrayIterator(array($rs1, $rs2)))); $collection->expects($this->any())->method('getFilename')->will($this->returnValue('abc')); $collection->expects($this->any())->method('asArray')->will($this->returnValue(array(array('loc' => 5), array('loc' => 15)))); $bounds = new Bounds(); // grouped results $groupedResults = new ResultCollection(); $result = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultAggregate')->disableOriginalConstructor()->getMock(); $result->expects($this->any())->method('getName')->will($this->returnValue('path1')); $result->expects($this->any())->method('getBounds')->will($this->returnValue($this->getMock('\\Hal\\Component\\Bounds\\Result\\ResultInterface'))); $groupedResults->push($result); $result = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultAggregate')->disableOriginalConstructor()->getMock(); $result->expects($this->any())->method('getName')->will($this->returnValue('path2')); $result->expects($this->any())->method('getBounds')->will($this->returnValue($this->getMock('\\Hal\\Component\\Bounds\\Result\\ResultInterface'))); $groupedResults->push($result); // formater $ruleSet = $this->getMock('\\Hal\\Application\\Rule\\RuleSet'); $ruleSet->expects($this->any())->method('getRule')->will($this->returnValue(array(3, 2, 1.5))); $validator = $this->getMockBuilder('\\Hal\\Application\\Rule\\Validator')->disableOriginalConstructor()->getMock(); $validator->expects($this->any())->method('getRuleSet')->willReturn($ruleSet); $formater = new Xml($validator, $bounds); $output = $formater->terminate($collection, $groupedResults); $xml = new \SimpleXMLElement($output); $p = $xml->xpath('//pmd/file/violation'); $this->assertCount(2, $p); $this->assertEquals('loc', $p[0]['rule']); $this->assertEquals('5', $p[0]['endline']); $this->assertEquals('loc', $p[1]['rule']); $this->assertEquals('15', $p[1]['endline']); }
public function testICanKnowTheInstabilityOfPackage() { $results = new ResultCollection(); $coupling = $this->getMockBuilder('\\Hal\\Metrics\\Complexity\\Structural\\HenryAndKafura\\Result')->disableOriginalConstructor()->getMock(); $coupling->expects($this->any())->method('getAfferentCoupling')->will($this->returnValue(1.5)); $coupling->expects($this->any())->method('getEfferentCoupling')->will($this->returnValue(0.8)); $resultSet = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $resultSet->expects($this->any())->method('getCoupling')->will($this->returnValue($coupling)); $results->push($resultSet); $instability = new Instability(); $r = $instability->calculate($results); $this->assertEquals(0.35, $r->getInstability()); }
public function testICanAcessToResultCollectionAsAnArray() { $rs1 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $rs1->expects($this->once())->method('getName')->will($this->returnValue('f1.php')); $rs2 = $this->getMockBuilder('\\Hal\\Component\\Result\\ResultSet')->disableOriginalConstructor()->getMock(); $collection = new ResultCollection(); $collection->push($rs1); $collection['f2.php'] = $rs2; $i = 0; foreach ($collection as $n) { $i++; } $this->assertEquals(2, $i); $this->assertEquals(2, sizeof($collection)); $this->assertEquals($rs1, $collection['f1.php']); unset($collection['f2.php']); $this->assertEquals(1, sizeof($collection)); $this->assertFalse(isset($collection['f2.php'])); }
/** * @inheritdoc */ public function execute(ResultCollection $collection, ResultCollection $aggregatedResults) { $this->output->write(str_pad("\rGrouping results by package/directory. This will take few minutes...", 80, " ")); // Aggregates results $groupedResults = $this->aggregator->aggregates($collection); // metrics tools $abstractness = new Abstractness(); $bounds = new Bounds(); $instability = new Instability(); foreach ($groupedResults as $namespace => $results) { // we filter aggregates to conserve only direct results $childs = new ResultCollection(); foreach ($results as $r) { if ($namespace === dirname($r->getName())) { $childs->push($r); } } $resultAggregate = new ResultAggregate($namespace); $resultAggregate->setAbstractness($abstractness->calculate($results))->setInstability($instability->calculate($results))->setBounds($bounds->calculate($results))->setChilds($childs); $aggregatedResults->push($resultAggregate); } }
/** * @inheritdoc */ public function execute(ResultCollection $collection, ResultCollection $aggregatedResults) { $files = $this->finder->find($this->path); if (0 == sizeof($files, COUNT_NORMAL)) { throw new \LogicException('No file found'); } $progress = new ProgressBar($this->output); $progress->start(sizeof($files, COUNT_NORMAL)); // tools $classMap = new ClassMap(); $tokenizer = new Tokenizer(); $syntaxChecker = new SyntaxChecker(); $fileAnalyzer = new FileAnalyzer($this->output, $this->withOOP, new Extractor($tokenizer), new \Hal\Metrics\Complexity\Text\Halstead\Halstead($tokenizer, new \Hal\Component\Token\TokenType()), new \Hal\Metrics\Complexity\Text\Length\Loc($tokenizer), new \Hal\Metrics\Design\Component\MaintainabilityIndex\MaintainabilityIndex(), new \Hal\Metrics\Complexity\Component\McCabe\McCabe($tokenizer), new \Hal\Metrics\Complexity\Component\Myer\Myer($tokenizer), $classMap); foreach ($files as $k => $filename) { $progress->advance(); // Integrity if (!$syntaxChecker->isCorrect($filename)) { $this->output->writeln(sprintf('<error>file %s is not valid and has been skipped</error>', $filename)); unset($files[$k]); continue; } // Analyze try { $resultSet = $fileAnalyzer->execute($filename); } catch (\Exception $e) { throw new \Exception(sprintf("a '%s' exception occured analyzing file %s\nMessage: %s", get_class($e), $filename, $e->getMessage()) . sprintf("\n------------\nStack:\n%s", $e->getTraceAsString()) . sprintf("\n------------\nDo not hesitate to report a bug: https://github.com/Halleck45/PhpMetrics/issues"), 0, $e->getPrevious()); } $collection->push($resultSet); } $progress->clear(); $progress->finish(); if ($this->withOOP) { // COUPLING (should be done after parsing files) $this->output->write(str_pad("\rAnalyzing coupling. This will take few minutes...", 80, " ")); $couplingAnalyzer = new CouplingAnalyzer($classMap, $collection); $couplingAnalyzer->execute($files); // LCOM (should be done after parsing files) $this->output->write(str_pad("\rLack of cohesion of method (lcom). This will take few minutes...", 80, " ")); $lcomAnalyzer = new LcomAnalyzer($classMap, $collection); $lcomAnalyzer->execute($files); // Card and Agresti (should be done after parsing files) $this->output->write(str_pad("\rAnalyzing System complexity. This will take few minutes...", 80, " ")); $lcomAnalyzer = new CardAndAgrestiAnalyzer($classMap, $collection); $lcomAnalyzer->execute($files); } }
/** * @inheritdoc */ public function execute(ResultCollection $collection, ResultCollection $aggregatedResults) { $files = $this->finder->find($this->path); if (0 == sizeof($files, COUNT_NORMAL)) { throw new \LogicException('No file found'); } $progress = new ProgressHelper(); $progress->start($this->output, sizeof($files, COUNT_NORMAL)); // tools $classMap = new ClassMap(); $tokenizer = new Tokenizer(); $syntaxChecker = new SyntaxChecker(); $fileAnalyzer = new FileAnalyzer($this->output, $this->withOOP, new Extractor($tokenizer), new \Hal\Metrics\Complexity\Text\Halstead\Halstead($tokenizer, new \Hal\Component\Token\TokenType()), new \Hal\Metrics\Complexity\Text\Length\Loc($tokenizer), new \Hal\Metrics\Design\Component\MaintenabilityIndex\MaintenabilityIndex($tokenizer), new \Hal\Metrics\Complexity\Component\McCabe\McCabe($tokenizer), new \Hal\Metrics\Complexity\Component\Myer\Myer($tokenizer), $classMap); foreach ($files as $k => $filename) { $progress->advance(); // Integrity if (!$syntaxChecker->isCorrect($filename)) { $this->output->writeln(sprintf('<error>file %s is not valid and has been skipped</error>', $filename)); unset($files[$k]); continue; } // Analyze $resultSet = $fileAnalyzer->execute($filename); $collection->push($resultSet); } $progress->clear(); $progress->finish(); if ($this->withOOP) { // COUPLING (should be done after parsing files) $this->output->write(str_pad("\rAnalyzing coupling. This will take few minutes...", 80, " ")); $couplingAnalyzer = new CouplingAnalyzer($classMap, $collection); $couplingAnalyzer->execute($files); // LCOM (should be done after parsing files) $this->output->write(str_pad("\rLack of cohesion of method (lcom). This will take few minutes...", 80, " ")); $lcomAnalyzer = new LcomAnalyzer($classMap, $collection); $lcomAnalyzer->execute($files); // Card and Agresti (should be done after parsing files) $this->output->write(str_pad("\rAnalyzing System complexity. This will take few minutes...", 80, " ")); $lcomAnalyzer = new CardAndAgrestiAnalyzer($classMap, $collection); $lcomAnalyzer->execute($files); } }