Skip to content

Commit

Permalink
Backport: Update "health score" (formerly "magic number") logic to ac…
Browse files Browse the repository at this point in the history
…count for config files (#129)
  • Loading branch information
TravisCarden authored Feb 2, 2021
1 parent 47d002f commit b4ca237
Show file tree
Hide file tree
Showing 5 changed files with 378 additions and 51 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ branches:
only:
- master
- develop
- support/2
- wip

env:
Expand Down
38 changes: 38 additions & 0 deletions src/Console/Helper/BorderlessTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Acquia\Orca\Console\Helper;

use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableStyle;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Provides a table for status displays.
*/
class BorderlessTable extends Table {

/**
* Constructs an instance.
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
* The output decorator.
*/
public function __construct(OutputInterface $output) {
parent::__construct($output);
$this->setStyle($this->tableStyle());
}

/**
* Provides the table style.
*
* @return \Symfony\Component\Console\Helper\TableStyle
* A TableStyle object.
*/
private function tableStyle(): TableStyle {
return (new TableStyle())
->setHorizontalBorderChars('', '')
->setVerticalBorderChars('', '')
->setDefaultCrossingChar('');
}

}
147 changes: 122 additions & 25 deletions src/Domain/Tool/Coverage/CodeCoverageReportBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Acquia\Orca\Helper\Filesystem\OrcaPathHandler;
use Noodlehaus\Exception\FileNotFoundException as NoodlehausFileNotFoundException;
use Noodlehaus\Exception\ParseException as NoodlehausParseException;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Finder\Exception\DirectoryNotFoundException as FinderDirectoryNotFoundException;

/**
Expand Down Expand Up @@ -54,6 +53,13 @@ class CodeCoverageReportBuilder {
*/
private $finderFactory;

/**
* The number of exported config files.
*
* @var int
*/
private $numConfigFiles = 0;

/**
* The ORCA path handler.
*
Expand All @@ -78,7 +84,7 @@ class CodeCoverageReportBuilder {
/**
* The data on tests.
*
* @var int[]
* @var array
*/
private $testsData = [
'classes' => 0,
Expand Down Expand Up @@ -147,8 +153,14 @@ private function ensurePreconditions(): void {
* In case of error.
*/
private function compileData(): void {
$this->getPhplocData();
$this->getTestsData();
try {
$this->getPhplocData();
$this->getTestsData();
$this->getConfigFilesData();
}
catch (FinderDirectoryNotFoundException $e) {
throw new OrcaDirectoryNotFoundException($e->getMessage());
}
}

/**
Expand Down Expand Up @@ -182,16 +194,11 @@ private function getPhplocData(): void {
*/
private function getTestsData(): void {
$finder = $this->finderFactory->create();
try {
$classes = $finder
->in($this->path)
->name('*Test.php')
->notPath(self::FINDER_PATH_EXCLUSIONS)
->contains('public function test');
}
catch (FinderDirectoryNotFoundException $e) {
throw new OrcaDirectoryNotFoundException($e->getMessage());
}
$classes = $finder
->in($this->path)
->name('*Test.php')
->notPath(self::FINDER_PATH_EXCLUSIONS)
->contains('public function test');

$this->testsData['classes'] = iterator_count($classes);

Expand All @@ -202,20 +209,70 @@ private function getTestsData(): void {
}
}

/**
* Gets the config files data.
*/
private function getConfigFilesData(): void {
$paths = $this->getExtensionPaths();
foreach ($paths as $path) {
$this->countConfigFiles($path);
}
}

/**
* Gets the paths to Drupal extensions.
*/
private function getExtensionPaths(): array {
$paths = [];

$finder = $this->finderFactory->create();
$info_files = $finder
->in($this->path)
->name('*.info.yml')
->notPath(self::FINDER_PATH_EXCLUSIONS)
->notPath('tests')
->files();

foreach ($info_files as $file) {
$paths[] = $file->getPath();
}

return $paths;
}

/**
* Counts exported configuration files under the given path.
*
* @param string $path
* The path to search for config files.
*
* @throws \Acquia\Orca\Exception\OrcaDirectoryNotFoundException
*/
private function countConfigFiles(string $path): void {
$finder = $this->finderFactory->create();
$config_files = $finder
->in($path)
->path('config')
->name('*.yml')
->notPath(self::FINDER_PATH_EXCLUSIONS)
->notPath('tests');
$this->numConfigFiles += iterator_count($config_files);
}

/**
* Compiles the report data into a table array.
*
* @return array
* The report data array.
*/
private function buildTable(): array {
$complexity = $this->phplocData['ccn'];
$assertions = $this->testsData['assertions'];
return [
[' Test assertions', $assertions],
['÷ Cyclomatic complexity', $complexity],
new TableSeparator(),
[' Magic number', $this->computeMagicNumber()],
['Health score', $this->computeHealthScore()],
[' Numerator', $this->computeNumerator()],
[' Test assertions', $this->getAssertions()],
[' Denominator', $this->computeDenominator()],
[' Cyclomatic complexity', $this->getComplexity()],
[' Exported config files', $this->numConfigFiles],
];
}

Expand All @@ -225,15 +282,55 @@ private function buildTable(): array {
* @return float
* The score as a floating point number.
*/
private function computeMagicNumber(): float {
$assertions = $this->testsData['assertions'];
$complexity = $this->phplocData['ccn'];
private function computeHealthScore(): float {
$numerator = $this->computeNumerator();
$denominator = $this->computeDenominator();

if (!$assertions || !$complexity) {
if (!$numerator || !$denominator) {
return 0;
}

return number_format($assertions / $complexity, 2);
return (float) number_format($numerator / $denominator, 2);
}

/**
* Computes the health score numerator.
*
* @return int
* The numerator.
*/
private function computeNumerator(): int {
return $this->getAssertions();
}

/**
* Computes the health score ratio denominator.
*
* @return int
* The denominator.
*/
private function computeDenominator(): int {
return $this->getComplexity() + $this->numConfigFiles;
}

/**
* Gets the number of test assertions.
*
* @return int
* The number of assetions.
*/
private function getAssertions(): int {
return $this->testsData['assertions'];
}

/**
* Gets the cyclomatic complexity.
*
* @return int
* The cyclomatic complexity.
*/
private function getComplexity(): int {
return $this->phplocData['ccn'];
}

}
6 changes: 3 additions & 3 deletions src/Domain/Tool/Coverage/CoverageTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Acquia\Orca\Domain\Tool\Coverage;

use Acquia\Orca\Console\Helper\StatusTable;
use Acquia\Orca\Console\Helper\BorderlessTable;
use Acquia\Orca\Domain\Tool\TaskInterface;
use Acquia\Orca\Exception\OrcaFileNotFoundException;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -52,7 +52,7 @@ public function __construct(CodeCoverageReportBuilder $coverage_report_builder,
public function execute(): void {
try {
$rows = $this->builder->build($this->path);
(new StatusTable($this->output))
(new BorderlessTable($this->output))
->setRows($rows)
->render();
}
Expand Down Expand Up @@ -81,7 +81,7 @@ public function label(): string {
* {@inheritdoc}
*/
public function statusMessage(): string {
return 'Estimating Code Coverage';
return 'Generating health score';
}

}
Loading

0 comments on commit b4ca237

Please sign in to comment.