diff --git a/public/assets/js/build-plugins/phpunit-coverage.js b/public/assets/js/build-plugins/phpunit-coverage.js new file mode 100644 index 00000000..5f5eaeb8 --- /dev/null +++ b/public/assets/js/build-plugins/phpunit-coverage.js @@ -0,0 +1,108 @@ +var coveragePlugin = ActiveBuild.UiPlugin.extend({ + id: 'build-phpunit-coverage-chart', + css: 'col-xs-12', + title: Lang.get('coverage'), + lastData: null, + displayOnUpdate: false, + rendered: false, + chartData: null, + + register: function () { + var self = this; + var query = ActiveBuild.registerQuery('phpunit-coverage', -1, {num_builds: 10, key: 'phpunit-coverage'}) + + $(window).on('phpunit-coverage', function (data) { + self.onUpdate(data); + }); + + $(window).on('build-updated', function (data) { + if (data.queryData && data.queryData.status > 1 && !self.rendered) { + query(); + } + }); + }, + + render: function () { + var self = this; + var container = $('
'); + + container.append(''); + + $(document).on('shown.bs.tab', function () { + $('#build-phpunit-coverage-chart').hide(); + self.drawChart(); + }); + + return container; + }, + + onUpdate: function (e) { + this.lastData = e.queryData; + this.displayChart(); + }, + + displayChart: function () { + var self = this; + var builds = this.lastData; + self.rendered = true; + + self.chartData = { + labels: [], + datasets: [ + { + label: Lang.get('classes'), + strokeColor: "#555299", + pointColor: "#555299", + data: [] + }, + { + label: Lang.get('methods'), + strokeColor: "#00A65A", + pointColor: "#00A65A", + data: [] + }, + { + label: Lang.get('lines'), + strokeColor: "#8AA4AF", + pointColor: "#8AA4AF", + data: [] + } + ] + }; + + for (var i in builds) { + self.chartData.labels.push(Lang.get('build') + ' ' + builds[i].build_id); + self.chartData.datasets[0].data.push(builds[i].meta_value.classes); + self.chartData.datasets[1].data.push(builds[i].meta_value.methods); + self.chartData.datasets[2].data.push(builds[i].meta_value.lines); + } + + self.drawChart(); + }, + + drawChart: function () { + var self = this; + + if ($('#information').hasClass('active') && self.chartData && self.lastData) { + $('#build-phpunit-coverage-chart').show(); + + var ctx = $("#phpunit-coverage-chart").get(0).getContext("2d"); + var chart = new Chart(ctx, { + responsive: true + }); + + Chart.defaults.global.responsive = true; + + chart.Line(self.chartData, { + scaleOverride : true, + scaleSteps : 10, + scaleStepWidth : 10, + scaleStartValue : 0, + datasetFill: false, + multiTooltipTemplate: "<%=datasetLabel%>: <%= value %>" + }); + } + } +}); + +ActiveBuild.registerPlugin(new coveragePlugin()); diff --git a/public/assets/js/build.js b/public/assets/js/build.js index f0f1f479..e738acb5 100644 --- a/public/assets/js/build.js +++ b/public/assets/js/build.js @@ -122,7 +122,11 @@ var Build = Class.extend({ if (renderOrder) { renderOrder = JSON.parse(renderOrder); } else { - renderOrder = ['build-lines-chart', 'build-warnings-chart']; + renderOrder = [ + 'build-lines-chart', + 'build-warnings-chart', + 'build-phpunit-coverage-chart' + ]; } for (var idx in renderOrder) { diff --git a/src/PHPCensor/Languages/lang.en.php b/src/PHPCensor/Languages/lang.en.php index ade38d25..991f39af 100644 --- a/src/PHPCensor/Languages/lang.en.php +++ b/src/PHPCensor/Languages/lang.en.php @@ -199,12 +199,15 @@ PHP Censor', 'chart_display' => 'This chart will display once the build has completed.', - 'build' => 'Build', - 'lines' => 'Lines', + 'build' => 'Build', + 'lines' => 'Lines', + 'classes' => 'Classes', + 'methods' => 'Methods', 'comment_lines' => 'Comment lines', 'noncomment_lines' => 'Non-Comment lines', 'logical_lines' => 'Logical Lines', 'lines_of_code' => 'Lines of code', + 'coverage' => 'PHPUnit code coverage', 'build_log' => 'Build log', 'quality_trend' => 'Quality trend', 'codeception_errors' => 'Codeception errors', diff --git a/src/PHPCensor/Languages/lang.ru.php b/src/PHPCensor/Languages/lang.ru.php index fd3f7f0a..687e3393 100644 --- a/src/PHPCensor/Languages/lang.ru.php +++ b/src/PHPCensor/Languages/lang.ru.php @@ -192,12 +192,15 @@ PHP Censor', 'chart_display' => 'Этот график будет показан после окончания сборки.', - 'build' => 'Сборка', - 'lines' => 'Строк', + 'build' => 'Сборка', + 'lines' => 'Строк', + 'classes' => 'Классов', + 'methods' => 'Методов', 'comment_lines' => 'Строк комментариев', 'noncomment_lines' => 'Строк некомментариев', 'logical_lines' => 'Строк логики', 'lines_of_code' => 'Строк кода', + 'coverage' => 'Покрытие кода тестами PHPUnit', 'build_log' => 'Лог сборки', 'quality_trend' => 'Тенденция качества', 'codeception_errors' => 'Ошибки Codeception', diff --git a/src/PHPCensor/Plugin/Option/PhpUnitOptions.php b/src/PHPCensor/Plugin/Option/PhpUnitOptions.php index 5ca869de..6a53599e 100644 --- a/src/PHPCensor/Plugin/Option/PhpUnitOptions.php +++ b/src/PHPCensor/Plugin/Option/PhpUnitOptions.php @@ -121,6 +121,7 @@ class PhpUnitOptions */ if (isset($this->options['coverage']) && $this->options['coverage']) { $this->addArgument('coverage-html', $this->location); + $this->addArgument('coverage-text'); } /* @@ -141,7 +142,7 @@ class PhpUnitOptions * @param string $argumentName * @param string $argumentValue */ - public function addArgument($argumentName, $argumentValue) + public function addArgument($argumentName, $argumentValue = null) { if (isset($this->arguments[$argumentName])) { if (!is_array($this->arguments[$argumentName])) { diff --git a/src/PHPCensor/Plugin/PhpUnit.php b/src/PHPCensor/Plugin/PhpUnit.php index 5a799f34..2cb0cd44 100644 --- a/src/PHPCensor/Plugin/PhpUnit.php +++ b/src/PHPCensor/Plugin/PhpUnit.php @@ -136,7 +136,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface // Save the results into a log file $logFile = @tempnam($buildPath, 'jLog_'); - $options->addArgument('log-'.$logFormat, $logFile); + $options->addArgument('log-' . $logFormat, $logFile); // Removes any current configurations files $options->removeArgument('configuration'); @@ -152,12 +152,25 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface $arguments = $this->builder->interpolate($options->buildArgumentString()); $cmd = $this->findBinary('phpunit') . ' %s %s'; $success = $this->builder->executeCommand($cmd, $arguments, $directory); + $output = $this->builder->getLastOutput(); $this->processResults($logFile, $logFormat); $config = $this->builder->getSystemConfig('php-censor'); if ($options->getOption('coverage')) { + preg_match( + '#Classes:[\s]*(.*?)%[^M]*?Methods:[\s]*(.*?)%[^L]*?Lines:[\s]*(.*?)\%#s', + $output, + $matches + ); + + $this->build->storeMeta('phpunit-coverage', [ + 'classes' => !empty($matches[1]) ? $matches[1] : '0.00', + 'methods' => !empty($matches[2]) ? $matches[2] : '0.00', + 'lines' => !empty($matches[3]) ? $matches[3] : '0.00', + ]); + $this->builder->logSuccess( sprintf( "\nPHPUnit successful.\nYou can use coverage report: %s", @@ -190,7 +203,10 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface $this->build->storeMeta('phpunit-errors', $parser->getFailures()); foreach ($parser->getErrors() as $error) { - $severity = $error['severity'] == $parser::SEVERITY_ERROR ? BuildError::SEVERITY_CRITICAL : BuildError::SEVERITY_HIGH; + $severity = $error['severity'] == + $parser::SEVERITY_ERROR ? + BuildError::SEVERITY_CRITICAL : + BuildError::SEVERITY_HIGH; $this->build->reportError( $this->builder, 'php_unit', $error['message'], $severity, $error['file'], $error['line'] ); diff --git a/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php b/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php index 96c932e4..a7c14779 100644 --- a/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php +++ b/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php @@ -140,8 +140,9 @@ class PhpUnitResultJson extends PhpUnitResult /** * Saves additional info for a failing test * - * @param array $data * @param array $event + * + * @return array */ protected function getFileAndLine($event) { diff --git a/tests/PHPCensor/Plugin/Option/PhpUnitOptionsTest.php b/tests/PHPCensor/Plugin/Option/PhpUnitOptionsTest.php index 490ddc15..f665ce3e 100644 --- a/tests/PHPCensor/Plugin/Option/PhpUnitOptionsTest.php +++ b/tests/PHPCensor/Plugin/Option/PhpUnitOptionsTest.php @@ -37,6 +37,7 @@ class PhpUnitOptionsTest extends \PHPUnit\Framework\TestCase ], [ 'coverage-html' => '/location', + 'coverage-text' => null, ], ], [ @@ -49,6 +50,7 @@ class PhpUnitOptionsTest extends \PHPUnit\Framework\TestCase ], [ 'coverage-html' => '/location', + 'coverage-text' => null, ], ], [