prepare for several types of phpunit results
This commit is contained in:
parent
a77b1115a0
commit
c3c103cc78
|
@ -7,7 +7,7 @@ use PHPCensor\Builder;
|
|||
use PHPCensor\Model\Build;
|
||||
use PHPCensor\Model\BuildError;
|
||||
use PHPCensor\Plugin\Option\PhpUnitOptions;
|
||||
use PHPCensor\Plugin\Util\PhpUnitResult;
|
||||
use PHPCensor\Plugin\Util\PhpUnitResultJson;
|
||||
use PHPCensor\Plugin;
|
||||
use PHPCensor\ZeroConfigPluginInterface;
|
||||
|
||||
|
@ -112,8 +112,8 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
|
|||
$buildPath = $this->build->getBuildPath() . DIRECTORY_SEPARATOR;
|
||||
|
||||
// Save the results into a json file
|
||||
$jsonFile = @tempnam($buildPath, 'jLog_');
|
||||
$options->addArgument('log-json', $jsonFile);
|
||||
$logFile = @tempnam($buildPath, 'jLog_');
|
||||
$options->addArgument('log-json', $logFile);
|
||||
|
||||
// Removes any current configurations files
|
||||
$options->removeArgument('configuration');
|
||||
|
@ -126,7 +126,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
|
|||
$cmd = $this->findBinary('phpunit') . ' %s %s';
|
||||
$success = $this->builder->executeCommand($cmd, $arguments, $directory);
|
||||
|
||||
$this->processResults($jsonFile);
|
||||
$this->processResults($logFile);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
|
|||
protected function processResults($jsonFile)
|
||||
{
|
||||
if (file_exists($jsonFile)) {
|
||||
$parser = new PhpUnitResult($jsonFile, $this->build->getBuildPath());
|
||||
$parser = new PhpUnitResultJson($logFile, $this->build->getBuildPath());
|
||||
|
||||
$this->build->storeMeta('phpunit-data', $parser->parse()->getResults());
|
||||
$this->build->storeMeta('phpunit-errors', $parser->getFailures());
|
||||
|
@ -152,9 +152,9 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
|
|||
$this->builder, 'php_unit', $error['message'], $severity, $error['file'], $error['line']
|
||||
);
|
||||
}
|
||||
@unlink($jsonFile);
|
||||
@unlink($logFile);
|
||||
} else {
|
||||
throw new \Exception('JSON output file does not exist: ' . $jsonFile);
|
||||
throw new \Exception('log output file does not exist: ' . $logFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,19 +7,15 @@ namespace PHPCensor\Plugin\Util;
|
|||
*
|
||||
* @author Pablo Tejada <pablo@ptejada.com>
|
||||
*/
|
||||
class PhpUnitResult
|
||||
abstract class PhpUnitResult
|
||||
{
|
||||
const EVENT_TEST = 'test';
|
||||
const EVENT_TEST_START = 'testStart';
|
||||
const EVENT_SUITE_START = 'suiteStart';
|
||||
|
||||
const SEVERITY_PASS = 'success';
|
||||
const SEVERITY_FAIL = 'fail';
|
||||
const SEVERITY_ERROR = 'error';
|
||||
const SEVERITY_SKIPPED = 'skipped';
|
||||
|
||||
protected $options;
|
||||
protected $arguments = [];
|
||||
protected $outputFile;
|
||||
protected $buildPath;
|
||||
protected $results;
|
||||
protected $failures = 0;
|
||||
protected $errors = [];
|
||||
|
@ -36,158 +32,48 @@ class PhpUnitResult
|
|||
* @return $this
|
||||
* @throws \Exception If fails to parse the output
|
||||
*/
|
||||
public function parse()
|
||||
abstract public function parse();
|
||||
|
||||
abstract protected function getSeverity($testcase);
|
||||
|
||||
abstract protected function buildMessage($testcase);
|
||||
|
||||
abstract protected function buildTrace($testcase);
|
||||
|
||||
protected function getFileAndLine($testcase)
|
||||
{
|
||||
$rawResults = file_get_contents($this->outputFile);
|
||||
|
||||
$events = [];
|
||||
if ($rawResults && $rawResults[0] == '{') {
|
||||
$fixedJson = '[' . str_replace('}{', '},{', $rawResults) . ']';
|
||||
$events = json_decode($fixedJson, true);
|
||||
} elseif ($rawResults) {
|
||||
$events = json_decode($rawResults, true);
|
||||
}
|
||||
|
||||
// Reset the parsing variables
|
||||
$this->results = [];
|
||||
$this->errors = [];
|
||||
$this->failures = 0;
|
||||
|
||||
if ($events) {
|
||||
foreach ($events as $event) {
|
||||
if (isset($event['event']) && $event['event'] == self::EVENT_TEST) {
|
||||
$this->results[] = $this->parseEvent($event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $testcase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a test event
|
||||
*
|
||||
* @param array $event
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function parseEvent($event)
|
||||
protected function getOutput($testcase)
|
||||
{
|
||||
list($pass, $severity) = $this->getStatus($event);
|
||||
return $testcase['output'];
|
||||
}
|
||||
|
||||
protected function parseTestcase($testcase)
|
||||
{
|
||||
$severity = $this->getSeverity($testcase);
|
||||
$pass = isset(array_fill_keys([self::SEVERITY_PASS, self::SEVERITY_SKIPPED], true)[$severity]);
|
||||
$data = [
|
||||
'pass' => $pass,
|
||||
'severity' => $severity,
|
||||
'message' => $this->buildMessage($event),
|
||||
'trace' => $pass ? [] : $this->buildTrace($event),
|
||||
'output' => $event['output'],
|
||||
'message' => $this->buildMessage($testcase),
|
||||
'trace' => $pass ? [] : $this->buildTrace($testcase),
|
||||
'output' => $this->getOutput($testcase),
|
||||
];
|
||||
|
||||
if (!$pass) {
|
||||
$this->failures++;
|
||||
$this->addError($data, $event);
|
||||
$info = $this->getFileAndLine($testcase);
|
||||
$this->errors[] = [
|
||||
'message' => $data['message'],
|
||||
'severity' => $severity,
|
||||
'file' => $info['file'],
|
||||
'line' => $info['line'],
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the status of the event
|
||||
*
|
||||
* @param $event
|
||||
*
|
||||
* @return mixed[bool,string] - The pass and severity flags
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getStatus($event)
|
||||
{
|
||||
$status = $event['status'];
|
||||
switch ($status) {
|
||||
case 'fail':
|
||||
$pass = false;
|
||||
$severity = self::SEVERITY_FAIL;
|
||||
break;
|
||||
case 'error':
|
||||
if (strpos($event['message'], 'Skipped') === 0 || strpos($event['message'], 'Incomplete') === 0) {
|
||||
$pass = true;
|
||||
$severity = self::SEVERITY_SKIPPED;
|
||||
} else {
|
||||
$pass = false;
|
||||
$severity = self::SEVERITY_ERROR;
|
||||
}
|
||||
break;
|
||||
case 'pass':
|
||||
$pass = true;
|
||||
$severity = self::SEVERITY_PASS;
|
||||
break;
|
||||
case 'warning':
|
||||
$pass = true;
|
||||
$severity = self::SEVERITY_PASS;
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Unexpected PHPUnit test status: {$status}");
|
||||
break;
|
||||
}
|
||||
|
||||
return [$pass, $severity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message string for an event
|
||||
*
|
||||
* @param array $event
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildMessage($event)
|
||||
{
|
||||
$message = $event['test'];
|
||||
|
||||
if ($event['message']) {
|
||||
$message .= PHP_EOL . $event ['message'];
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a string base trace of the failure
|
||||
*
|
||||
* @param array $event
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function buildTrace($event)
|
||||
{
|
||||
$formattedTrace = [];
|
||||
|
||||
if (!empty($event['trace'])) {
|
||||
foreach ($event['trace'] as $step){
|
||||
$line = str_replace($this->buildPath, '', $step['file']) . ':' . $step['line'];
|
||||
$formattedTrace[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $formattedTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves additional info for a failing test
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $event
|
||||
*/
|
||||
protected function addError($data, $event)
|
||||
{
|
||||
$firstTrace = end($event['trace']);
|
||||
reset($event['trace']);
|
||||
|
||||
$this->errors[] = [
|
||||
'message' => $data['message'],
|
||||
'severity' => $data['severity'],
|
||||
'file' => str_replace($this->buildPath, '', $firstTrace['file']),
|
||||
'line' => $firstTrace['line'],
|
||||
];
|
||||
$this->results[] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
145
src/PHPCensor/Plugin/Util/PhpUnitResultJson.php
Normal file
145
src/PHPCensor/Plugin/Util/PhpUnitResultJson.php
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCensor\Plugin\Util;
|
||||
|
||||
/**
|
||||
* Class PhpUnitResult parses the results for the PhpUnitV2 plugin
|
||||
*
|
||||
* @author Pablo Tejada <pablo@ptejada.com>
|
||||
*/
|
||||
class PhpUnitResultJson extends PhpUnitResult
|
||||
{
|
||||
const EVENT_TEST = 'test';
|
||||
const EVENT_TEST_START = 'testStart';
|
||||
const EVENT_SUITE_START = 'suiteStart';
|
||||
|
||||
protected $options;
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* Parse the results
|
||||
*
|
||||
* @return $this
|
||||
* @throws \Exception If fails to parse the output
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
$rawResults = file_get_contents($this->outputFile);
|
||||
|
||||
$events = [];
|
||||
if ($rawResults && $rawResults[0] == '{') {
|
||||
$fixedJson = '[' . str_replace('}{', '},{', $rawResults) . ']';
|
||||
$events = json_decode($fixedJson, true);
|
||||
} elseif ($rawResults) {
|
||||
$events = json_decode($rawResults, true);
|
||||
}
|
||||
|
||||
// Reset the parsing variables
|
||||
$this->results = [];
|
||||
$this->errors = [];
|
||||
$this->failures = 0;
|
||||
|
||||
if ($events) {
|
||||
foreach ($events as $event) {
|
||||
if (isset($event['event']) && $event['event'] == self::EVENT_TEST) {
|
||||
$this->parseTestcase($event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the severity of the event
|
||||
*
|
||||
* @param $event
|
||||
*
|
||||
* @return string The severity flags
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getSeverity($event)
|
||||
{
|
||||
$status = $event['status'];
|
||||
switch ($status) {
|
||||
case 'fail':
|
||||
$severity = self::SEVERITY_FAIL;
|
||||
break;
|
||||
case 'error':
|
||||
if (strpos($event['message'], 'Skipped') === 0 || strpos($event['message'], 'Incomplete') === 0) {
|
||||
$severity = self::SEVERITY_SKIPPED;
|
||||
} else {
|
||||
$severity = self::SEVERITY_ERROR;
|
||||
}
|
||||
break;
|
||||
case 'pass':
|
||||
$severity = self::SEVERITY_PASS;
|
||||
break;
|
||||
case 'warning':
|
||||
$severity = self::SEVERITY_PASS;
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Unexpected PHPUnit test status: {$status}");
|
||||
break;
|
||||
}
|
||||
|
||||
return $severity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message string for an event
|
||||
*
|
||||
* @param array $event
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildMessage($event)
|
||||
{
|
||||
$message = $event['test'];
|
||||
|
||||
if ($event['message']) {
|
||||
$message .= PHP_EOL . $event ['message'];
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a string base trace of the failure
|
||||
*
|
||||
* @param array $event
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function buildTrace($event)
|
||||
{
|
||||
$formattedTrace = [];
|
||||
|
||||
if (!empty($event['trace'])) {
|
||||
foreach ($event['trace'] as $step){
|
||||
$line = str_replace($this->buildPath, '', $step['file']) . ':' . $step['line'];
|
||||
$formattedTrace[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $formattedTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves additional info for a failing test
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $event
|
||||
*/
|
||||
protected function getFileAndLine($event)
|
||||
{
|
||||
$firstTrace = end($event['trace']);
|
||||
reset($event['trace']);
|
||||
|
||||
return [
|
||||
'file' => str_replace($this->buildPath, '', $firstTrace['file']),
|
||||
'line' => $firstTrace['line']
|
||||
];
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Tests\PHPCensor\Plugin\Util;
|
||||
|
||||
use PHPCensor\Plugin\Util\PhpUnitResult;
|
||||
use PHPCensor\Plugin\Util\PhpUnitResultJson;
|
||||
|
||||
/**
|
||||
* Class PhpUnitResultTest parses the results for the PhpUnitV2 plugin
|
||||
|
@ -16,7 +17,7 @@ class PhpUnitResultTest extends \PHPUnit_Framework_TestCase
|
|||
public function testInitParse()
|
||||
{
|
||||
$buildPath = '/path/to/build';
|
||||
$parser = new PhpUnitResult(ROOT_DIR . 'tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt', $buildPath);
|
||||
$parser = new PhpUnitResultJson(ROOT_DIR . 'tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt', $buildPath);
|
||||
$output = $parser->parse()->getResults();
|
||||
$errors = $parser->getErrors();
|
||||
|
||||
|
|
Loading…
Reference in a new issue