Updating PHPUnit plugin to provide a report like PHPMD and PHPCS, fixes #305
This commit is contained in:
parent
4c8083602a
commit
03f3b15fb8
|
@ -42,7 +42,7 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
$path = $phpci->buildPath;
|
||||
$this->phpci = $phpci;
|
||||
$this->directory = isset($options['directory']) ? $path . '/' . $options['directory'] : $path;
|
||||
$this->action = isset($options['action']) ? $options['action'] : 'update';
|
||||
$this->action = isset($options['action']) ? $options['action'] : 'install';
|
||||
$this->preferDist = isset($options['prefer_dist']) ? $options['prefer_dist'] : true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace PHPCI\Plugin;
|
|||
use PHPCI;
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Plugin\Util\TapParser;
|
||||
|
||||
/**
|
||||
* PHP Unit Plugin - Allows PHP Unit testing.
|
||||
|
@ -23,6 +24,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
{
|
||||
protected $args;
|
||||
protected $phpci;
|
||||
protected $build;
|
||||
|
||||
/**
|
||||
* @var string|string[] $directory The directory (or array of dirs) to run PHPUnit on
|
||||
|
@ -58,20 +60,20 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
|
||||
public static function findConfigFile($buildPath)
|
||||
{
|
||||
if (file_exists($buildPath . '/phpunit.xml')) {
|
||||
return $buildPath . '/phpunit.xml';
|
||||
if (file_exists($buildPath . 'phpunit.xml')) {
|
||||
return 'phpunit.xml';
|
||||
}
|
||||
|
||||
if (file_exists($buildPath . '/tests/phpunit.xml')) {
|
||||
return $buildPath . '/tests/phpunit.xml';
|
||||
if (file_exists($buildPath . 'tests/phpunit.xml')) {
|
||||
return 'tests/phpunit.xml';
|
||||
}
|
||||
|
||||
if (file_exists($buildPath . '/phpunit.xml.dist')) {
|
||||
return $buildPath . '/phpunit.xml.dist';
|
||||
if (file_exists($buildPath . 'phpunit.xml.dist')) {
|
||||
return 'phpunit.xml.dist';
|
||||
}
|
||||
|
||||
if (file_exists($buildPath . '/tests/phpunit.xml.dist')) {
|
||||
return $buildPath . '/tests/phpunit.xml.dist';
|
||||
if (file_exists($buildPath . 'tests/phpunit.xml.dist')) {
|
||||
return 'tests/phpunit.xml.dist';
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -80,9 +82,9 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
public function __construct(Builder $phpci, Build $build, array $options = array())
|
||||
{
|
||||
$this->phpci = $phpci;
|
||||
$this->build = $build;
|
||||
|
||||
if (!count($options)) {
|
||||
$this->runFrom = $phpci->buildPath;
|
||||
if (empty($options['config']) && empty($options['directory'])) {
|
||||
$this->xmlConfigFile = self::findConfigFile($phpci->buildPath);
|
||||
}
|
||||
|
||||
|
@ -118,6 +120,8 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
{
|
||||
$success = true;
|
||||
|
||||
$this->phpci->logExecOutput(false);
|
||||
|
||||
// Run any config files first. This can be either a single value or an array.
|
||||
if ($this->xmlConfigFile !== null) {
|
||||
$success &= $this->runConfigFile($this->xmlConfigFile);
|
||||
|
@ -128,6 +132,16 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
$success &= $this->runDir($this->directory);
|
||||
}
|
||||
|
||||
$output = $this->phpci->getLastOutput();
|
||||
$tapParser = new TapParser($output);
|
||||
$output = $tapParser->parse();
|
||||
$failures = $tapParser->getTotalFailures();
|
||||
|
||||
$this->build->storeMeta('phpunit-errors', $failures);
|
||||
$this->build->storeMeta('phpunit-data', $output);
|
||||
|
||||
$this->phpci->logExecOutput(true);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
|
@ -150,7 +164,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
}
|
||||
|
||||
|
||||
$cmd = $phpunit . ' %s -c "%s" ' . $this->coverage . $this->path;
|
||||
$cmd = $phpunit . ' --tap %s -c "%s" ' . $this->coverage . $this->path;
|
||||
$success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $configPath);
|
||||
|
||||
if ($this->runFrom) {
|
||||
|
@ -176,7 +190,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
return false;
|
||||
}
|
||||
|
||||
$cmd = $phpunit . ' %s "%s"';
|
||||
$cmd = $phpunit . ' --tap %s "%s"';
|
||||
$success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $dirPath);
|
||||
chdir($curdir);
|
||||
return $success;
|
||||
|
|
92
PHPCI/Plugin/Util/TapParser.php
Normal file
92
PHPCI/Plugin/Util/TapParser.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Util;
|
||||
|
||||
class TapParser
|
||||
{
|
||||
const TEST_COUNTS_PATTERN = '/([0-9]+)\.\.([0-9]+)/';
|
||||
const TEST_LINE_PATTERN = '/(ok|not ok)\s+[0-9]+\s+\-\s+([^\n]+)::([^\n]+)/';
|
||||
const TEST_MESSAGE_PATTERN = '/message\:\s+\'([^\']+)\'/';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tapString;
|
||||
|
||||
protected $failures = 0;
|
||||
|
||||
/**
|
||||
* Create a new TAP parser for a given string.
|
||||
* @param string $tapString The TAP format string to be parsed.
|
||||
*/
|
||||
public function __construct($tapString)
|
||||
{
|
||||
$this->tapString = trim($tapString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a given TAP format string and return an array of tests and their status.
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
// Split up the TAP string into an array of lines, then
|
||||
// trim all of the lines so there's no leading or trailing whitespace.
|
||||
$lines = explode("\n", $this->tapString);
|
||||
$lines = array_map(function ($line) {
|
||||
return trim($line);
|
||||
}, $lines);
|
||||
|
||||
// Check TAP version:
|
||||
$versionLine = array_shift($lines);
|
||||
|
||||
if ($versionLine != 'TAP version 13') {
|
||||
throw new \Exception('TapParser only supports TAP version 13');
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
$totalTests = 0;
|
||||
if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) {
|
||||
array_shift($lines);
|
||||
$totalTests = (int)$matches[2];
|
||||
}
|
||||
|
||||
if (preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) {
|
||||
array_pop($lines);
|
||||
$totalTests = (int)$matches[2];
|
||||
}
|
||||
|
||||
$rtn = array();
|
||||
foreach ($lines as $line) {
|
||||
$matches = array();
|
||||
|
||||
if (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) {
|
||||
$ok = ($matches[1] == 'ok' ? true : false);
|
||||
|
||||
if (!$ok) {
|
||||
$this->failures++;
|
||||
}
|
||||
|
||||
$item = array(
|
||||
'pass' => $ok,
|
||||
'suite' => $matches[2],
|
||||
'test' => $matches[3],
|
||||
);
|
||||
|
||||
$rtn[] = $item;
|
||||
} elseif (preg_match(self::TEST_MESSAGE_PATTERN, $line, $matches)) {
|
||||
$rtn[count($rtn) - 1]['message'] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($totalTests != count($rtn)) {
|
||||
throw new \Exception('Invalid TAP string, number of tests does not match specified test count.');
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function getTotalFailures()
|
||||
{
|
||||
return $this->failures;
|
||||
}
|
||||
}
|
65
public/assets/js/build-plugins/phpunit.js
Normal file
65
public/assets/js/build-plugins/phpunit.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
var phpunitPlugin = PHPCI.UiPlugin.extend({
|
||||
id: 'build-phpunit-errors',
|
||||
css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12',
|
||||
title: 'PHPUnit',
|
||||
lastData: null,
|
||||
displayOnUpdate: false,
|
||||
box: true,
|
||||
|
||||
register: function() {
|
||||
var self = this;
|
||||
var query = PHPCI.registerQuery('phpunit-data', -1, {key: 'phpunit-data'})
|
||||
|
||||
$(window).on('phpunit-data', function(data) {
|
||||
self.onUpdate(data);
|
||||
});
|
||||
|
||||
$(window).on('build-updated', function(data) {
|
||||
if (data.queryData.status > 1) {
|
||||
self.displayOnUpdate = true;
|
||||
query();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
return $('<table class="table table-striped" id="phpunit-data">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
' <th>Test</th>' +
|
||||
'</tr>' +
|
||||
'</thead><tbody></tbody></table>');
|
||||
},
|
||||
|
||||
onUpdate: function(e) {
|
||||
if (this.lastData && this.lastData[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastData = e.queryData;
|
||||
|
||||
var tests = this.lastData[0].meta_value;
|
||||
var tbody = $('#phpunit-data tbody');
|
||||
tbody.empty();
|
||||
|
||||
for (var i in tests) {
|
||||
|
||||
var row = $('<tr>' +
|
||||
'<td><strong>'+tests[i].suite+'' +
|
||||
'::'+tests[i].test+'</strong><br>' +
|
||||
''+(tests[i].message || '')+'</td>' +
|
||||
'</tr>');
|
||||
|
||||
if (!tests[i].pass) {
|
||||
row.addClass('danger');
|
||||
} else {
|
||||
row.addClass('success');
|
||||
}
|
||||
|
||||
tbody.append(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PHPCI.registerPlugin(new phpunitPlugin());
|
|
@ -3,10 +3,11 @@ var warningsPlugin = PHPCI.UiPlugin.extend({
|
|||
css: 'col-lg-6 col-md-6 col-sm-12 col-xs-12',
|
||||
title: 'Quality Trend',
|
||||
keys: {
|
||||
'phpmd-warnings': 'PHPMD Warnings',
|
||||
'phpcs-warnings': 'PHPCS Warnings',
|
||||
'phpcs-errors': 'PHPCS Errors',
|
||||
'phplint-errors': 'PHPLint Errors'
|
||||
'phpmd-warnings': 'PHPMD Warnings',
|
||||
'phpcs-warnings': 'PHPCS Warnings',
|
||||
'phpcs-errors': 'PHPCS Errors',
|
||||
'phplint-errors': 'PHPLint Errors',
|
||||
'phpunit-errors': 'PHPUnit Errors'
|
||||
},
|
||||
data: {},
|
||||
displayOnUpdate: false,
|
||||
|
@ -19,7 +20,7 @@ var warningsPlugin = PHPCI.UiPlugin.extend({
|
|||
queries.push(PHPCI.registerQuery(key, -1, {num_builds: 10, key: key}));
|
||||
}
|
||||
|
||||
$(window).on('phpmd-warnings phpcs-warnings phpcs-errors phplint-errors', function(data) {
|
||||
$(window).on('phpmd-warnings phpcs-warnings phpcs-errors phplint-errors phpunit-errors', function(data) {
|
||||
self.onUpdate(data);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue