From a77b1115a0ddfb3723b9a3c74cee0d71c2bbd5c9 Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Sat, 15 Jul 2017 04:01:37 +0200 Subject: [PATCH 1/9] merge similar run methods in PhpUnit --- src/PHPCensor/Plugin/PhpUnit.php | 44 ++++++-------------------- tests/PHPCensor/Plugin/PhpUnitTest.php | 19 +++++------ 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/PHPCensor/Plugin/PhpUnit.php b/src/PHPCensor/Plugin/PhpUnit.php index ad283284..a1100e3b 100644 --- a/src/PHPCensor/Plugin/PhpUnit.php +++ b/src/PHPCensor/Plugin/PhpUnit.php @@ -84,13 +84,13 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface // Run any directories if (!empty($directories)) { foreach ($directories as $directory) { - $success[] = $this->runDir($directory); + $success[] = $this->runConfig($directory, null); } } else { // Run any config files if (!empty($xmlConfigFiles)) { foreach ($xmlConfigFiles as $configFile) { - $success[] = $this->runConfigFile($configFile); + $success[] = $this->runConfig($this->options->getTestsPath(), $configFile); } } } @@ -99,42 +99,14 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface } /** - * Run the PHPUnit tests in a specific directory or array of directories. + * Run the tests defined in a PHPUnit config file or in a specific directory. * * @param $directory - * - * @return bool|mixed - */ - protected function runDir($directory) - { - $options = clone $this->options; - - $buildPath = $this->build->getBuildPath() . DIRECTORY_SEPARATOR; - - // Save the results into a json file - $jsonFile = @tempnam($buildPath, 'jLog_'); - $options->addArgument('log-json', $jsonFile); - - // Removes any current configurations files - $options->removeArgument('configuration'); - - $arguments = $this->builder->interpolate($options->buildArgumentString()); - $cmd = $this->findBinary('phpunit') . ' %s "%s"'; - $success = $this->builder->executeCommand($cmd, $arguments, $directory); - - $this->processResults($jsonFile); - - return $success; - } - - /** - * Run the tests defined in a PHPUnit config file. - * * @param $configFile * * @return bool|mixed */ - protected function runConfigFile($configFile) + protected function runConfig($directory, $configFile) { $options = clone $this->options; $buildPath = $this->build->getBuildPath() . DIRECTORY_SEPARATOR; @@ -145,12 +117,14 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface // Removes any current configurations files $options->removeArgument('configuration'); - // Only the add the configuration file been passed - $options->addArgument('configuration', $buildPath . $configFile); + if (null !== $configFile) { + // Only the add the configuration file been passed + $options->addArgument('configuration', $buildPath . $configFile); + } $arguments = $this->builder->interpolate($options->buildArgumentString()); $cmd = $this->findBinary('phpunit') . ' %s %s'; - $success = $this->builder->executeCommand($cmd, $arguments, $options->getTestsPath()); + $success = $this->builder->executeCommand($cmd, $arguments, $directory); $this->processResults($jsonFile); diff --git a/tests/PHPCensor/Plugin/PhpUnitTest.php b/tests/PHPCensor/Plugin/PhpUnitTest.php index bf21e79f..068151fa 100644 --- a/tests/PHPCensor/Plugin/PhpUnitTest.php +++ b/tests/PHPCensor/Plugin/PhpUnitTest.php @@ -15,8 +15,8 @@ class PhpUnitTest extends \PHPUnit_Framework_TestCase 'config' => ROOT_DIR . 'phpunit.xml' ]; - $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfigFile'])->getMock(); - $mockPlugin->expects($this->once())->method('runConfigFile')->with(ROOT_DIR . 'phpunit.xml'); + $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock(); + $mockPlugin->expects($this->once())->method('runConfig')->with(null, ROOT_DIR . 'phpunit.xml'); $mockPlugin->execute(); } @@ -30,9 +30,10 @@ class PhpUnitTest extends \PHPUnit_Framework_TestCase ] ]; - $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfigFile'])->getMock(); - $mockPlugin->expects($this->exactly(2))->method('runConfigFile')->withConsecutive( - [ROOT_DIR . 'phpunit1.xml'], [ROOT_DIR . 'phpunit2.xml'] + $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock(); + $mockPlugin->expects($this->exactly(2))->method('runConfig')->withConsecutive( + [null, ROOT_DIR . 'phpunit1.xml'], + [null, ROOT_DIR . 'phpunit2.xml'] ); $mockPlugin->execute(); @@ -68,8 +69,8 @@ class PhpUnitTest extends \PHPUnit_Framework_TestCase 'directory' => '/test/directory/one' ]; - $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runDir'])->getMock(); - $mockPlugin->expects($this->once())->method('runDir')->with('/test/directory/one'); + $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock(); + $mockPlugin->expects($this->once())->method('runConfig')->with('/test/directory/one', null); $mockPlugin->execute(); } @@ -83,8 +84,8 @@ class PhpUnitTest extends \PHPUnit_Framework_TestCase ] ]; - $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runDir'])->getMock(); - $mockPlugin->expects($this->exactly(2))->method('runDir')->withConsecutive( + $mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock(); + $mockPlugin->expects($this->exactly(2))->method('runConfig')->withConsecutive( ['/test/directory/one'], ['/test/directory/two'] ); From c3c103cc78362bda1a3d407e2a55b575e7556d36 Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Sat, 15 Jul 2017 02:18:07 +0200 Subject: [PATCH 2/9] prepare for several types of phpunit results --- src/PHPCensor/Plugin/PhpUnit.php | 14 +- src/PHPCensor/Plugin/Util/PhpUnitResult.php | 176 +++--------------- .../Plugin/Util/PhpUnitResultJson.php | 145 +++++++++++++++ .../Plugin/Util/PhpUnitResultTest.php | 3 +- 4 files changed, 185 insertions(+), 153 deletions(-) create mode 100644 src/PHPCensor/Plugin/Util/PhpUnitResultJson.php diff --git a/src/PHPCensor/Plugin/PhpUnit.php b/src/PHPCensor/Plugin/PhpUnit.php index a1100e3b..0e143e04 100644 --- a/src/PHPCensor/Plugin/PhpUnit.php +++ b/src/PHPCensor/Plugin/PhpUnit.php @@ -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); } } } diff --git a/src/PHPCensor/Plugin/Util/PhpUnitResult.php b/src/PHPCensor/Plugin/Util/PhpUnitResult.php index 000d2e70..10ef2fa1 100644 --- a/src/PHPCensor/Plugin/Util/PhpUnitResult.php +++ b/src/PHPCensor/Plugin/Util/PhpUnitResult.php @@ -7,19 +7,15 @@ namespace PHPCensor\Plugin\Util; * * @author Pablo Tejada */ -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; } /** diff --git a/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php b/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php new file mode 100644 index 00000000..c99704cb --- /dev/null +++ b/src/PHPCensor/Plugin/Util/PhpUnitResultJson.php @@ -0,0 +1,145 @@ + + */ +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'] + ]; + } +} diff --git a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php index 95eab8dd..55ea7f50 100644 --- a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php +++ b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php @@ -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(); From 03f2e353ebdec980d3c2d3efb3890eafe0b9b88a Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Mon, 17 Jul 2017 00:28:56 +0200 Subject: [PATCH 3/9] reorder test data so that it could really happen --- .../Plugin/SampleFiles/phpunit_money.txt | 49 ++++++------------- .../Plugin/Util/PhpUnitResultTest.php | 2 +- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt index 101cafc5..5afb5381 100644 --- a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt +++ b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt @@ -288,27 +288,6 @@ ], "message": "Skipped Test: This test is currently failing", "output": "" -}{ - "event": "testStart", - "suite": "", - "test": "Tests\\Money\\MoneyTest::testDepends1" -}{ - "event": "test", - "suite": "", - "test": "Tests\\Money\\MoneyTest::testDepends1", - "status": "fail", - "time": 0.00078010559082031, - "trace": [ - { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 105, - "function": "assertTrue", - "class": "PHPUnit_Framework_Assert", - "type": "::" - } - ], - "message": "Failed asserting that false is true.", - "output": "" }{ "event": "test", "suite": "", @@ -316,12 +295,25 @@ "status": "error", "time": 0, "trace": [], - "message": "Skipped Test: This test depends on \"Tests\\Money\\MoneyTest::testDepends1\" to pass.", + "message": "Skipped Test: This test depends on \"Tests\\Money\\MoneyTest::testFail\" to pass.", "output": "" }{ "event": "suiteStart", "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest", "tests": 23 +}{ + "event": "testStart", + "suite": "Tests\\Money\\MoneyTest", + "test": "Tests\\Money\\MoneyTest::testFactoryMethods" +}{ + "event": "test", + "suite": "Tests\\Money\\MoneyTest", + "test": "Tests\\Money\\MoneyTest::testFactoryMethods", + "status": "warning", + "time": 0.06482195854187, + "trace": [], + "message": "Trying to @cover or @use not existing method \"Monies::test\".", + "output": "" }{ "event": "suiteStart", "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", @@ -339,19 +331,6 @@ "trace": [], "message": "", "output": "" -}{ - "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFactoryMethods" -}{ - "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFactoryMethods", - "status": "warning", - "time": 0.06482195854187, - "trace": [], - "message": "Trying to @cover or @use not existing method \"Monies::test\".", - "output": "" }{ "event": "testStart", "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", diff --git a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php index 55ea7f50..6cd864cf 100644 --- a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php +++ b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php @@ -21,7 +21,7 @@ class PhpUnitResultTest extends \PHPUnit_Framework_TestCase $output = $parser->parse()->getResults(); $errors = $parser->getErrors(); - $this->assertEquals(8, $parser->getFailures()); + $this->assertEquals(7, $parser->getFailures()); $this->assertInternalType('array', $output); $this->assertInternalType('array', $errors); $this->assertNotEmpty($output); From 21c93ba5af7c4f1b8b0356e4911721d896aaf879 Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Mon, 17 Jul 2017 01:00:17 +0200 Subject: [PATCH 4/9] recreate test result with real test suite -- phpunit 4.8 --- .../Plugin/SampleFiles/phpunit_money.txt | 186 +++++++++--------- 1 file changed, 95 insertions(+), 91 deletions(-) diff --git a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt index 5afb5381..1fa3e178 100644 --- a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt +++ b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt @@ -1,11 +1,11 @@ { "event": "suiteStart", "suite": "Money Test Suite", - "tests": 61 + "tests": 18 }{ "event": "suiteStart", "suite": "Tests\\Money\\MoneyTest", - "tests": 15 + "tests": 3 }{ "event": "testStart", "suite": "Tests\\Money\\MoneyTest", @@ -45,24 +45,28 @@ "trace": [], "message": "", "output": "" +}{ + "event": "suiteStart", + "suite": "ExampleResults\\ExampleFailuresTest", + "tests": 12 }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure" + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure", "status": "error", "time": 0.0025370121002197, "trace": [ { "file": "\/path\/to\/build\/src\/Money.php", - "line": 335 + "line": 320 }, { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 43, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 15, "function": "divide", "class": "Money\\Money", "type": "->" @@ -72,18 +76,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure2" + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure2" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure2", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure2", "status": "fail", "time": 0.008944034576416, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 61, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 20, "function": "assertEquals", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -93,22 +97,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure3" -}{ - "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testMaxInit" + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testIncomplete" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testMaxInit", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testIncomplete", "status": "error", "time": 0.0074319839477539, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 36, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 25, "function": "markTestIncomplete", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -116,16 +116,20 @@ ], "message": "Incomplete Test: No yet finished...", "output": "" +}{ + "event": "testStart", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure3" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure3", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure3", "status": "fail", "time": 0.0014960765838623, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 66, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 30, "function": "assertEquals", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -135,43 +139,43 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure4" + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure4" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest", - "test": "Tests\\Money\\MoneyTest::testFailure4", + "suite": "ExampleResults\\ExampleFailuresTest", + "test": "ExampleResults\\ExampleFailuresTest::testFailure4", "status": "fail", "time": 0.0023319721221924, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 71, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 35, "function": "assertTrue", "class": "PHPUnit_Framework_Assert", "type": "::" } ], - "message": "Really? It should have been true\nFailed asserting that false is true.", + "message": "Failed asserting that false is true.", "output": "" }{ "event": "suiteStart", - "suite": "Tests\\Money\\MoneyTest::testFailure5", + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", "tests": 3 }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)" + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)", + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6)", "status": "fail", "time": 0.0025498867034912, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 82, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 43, "function": "assertSame", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -181,18 +185,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')" + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')", + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')", "status": "fail", "time": 0.00087904930114746, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 82, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 43, "function": "assertSame", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -202,18 +206,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))" + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'), array(5, 'five'), array(6, 'six'))" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testFailure5", - "test": "Tests\\Money\\MoneyTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))", + "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", + "test": "ExampleResults\\ExampleFailuresTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'), array(5, 'five'), array(6, 'six'))", "status": "fail", "time": 0.0010340213775635, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 82, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 43, "function": "assertSame", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -223,22 +227,22 @@ "output": "" }{ "event": "suiteStart", - "suite": "Tests\\Money\\MoneyTest::testSkipped", + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", "tests": 3 }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)" + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)", + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #0 (1, 2, 3, 4, 5, 6)", "status": "error", "time": 0.0041179656982422, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 99, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 51, "function": "markTestSkipped", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -248,18 +252,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')" + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')", + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #1 ('one', 'two', 'three', 'four', 'five', 'six')", "status": "error", "time": 0.00082302093505859, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 99, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 51, "function": "markTestSkipped", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -269,18 +273,18 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))" + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'), array(5, 'five'), array(6, 'six'))" }{ "event": "test", - "suite": "Tests\\Money\\MoneyTest::testSkipped", - "test": "Tests\\Money\\MoneyTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'))", + "suite": "ExampleResults\\ExampleFailuresTest::testSkipped", + "test": "ExampleResults\\ExampleFailuresTest::testSkipped with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'), array(5, 'five'), array(6, 'six'))", "status": "error", "time": 0.00070905685424805, "trace": [ { - "file": "\/path\/to\/build\/tests\/MoneyTest.php", - "line": 99, + "file": "\/path\/to\/build\/tests\/ExampleFailuresTest.php", + "line": 51, "function": "markTestSkipped", "class": "PHPUnit_Framework_Assert", "type": "::" @@ -291,18 +295,14 @@ }{ "event": "test", "suite": "", - "test": "Tests\\Money\\MoneyTest::testDepends1", + "test": "", "status": "error", "time": 0, "trace": [], - "message": "Skipped Test: This test depends on \"Tests\\Money\\MoneyTest::testFail\" to pass.", + "message": "Skipped Test: This test depends on \"ExampleResults\\ExampleFailuresTest::testFailure\" to pass.", "output": "" }{ - "event": "suiteStart", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest", - "tests": 23 -}{ - "event": "testStart", + "event": "testStart", "suite": "Tests\\Money\\MoneyTest", "test": "Tests\\Money\\MoneyTest::testFactoryMethods" }{ @@ -316,16 +316,20 @@ "output": "" }{ "event": "suiteStart", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", - "tests": 18 + "suite": "Tests\\IntlMoneyParserTest", + "tests": 2 +}{ + "event": "suiteStart", + "suite": "Tests\\IntlMoneyParserTest::testIntlParser", + "tests": 2 }{ "event": "testStart", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", - "test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)" + "suite": "Tests\\IntlMoneyParserTest::testIntlParser", + "test": "Tests\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)" }{ "event": "test", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", - "test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)", + "suite": "Tests\\IntlMoneyParserTest::testIntlParser", + "test": "Tests\\IntlMoneyParserTest::testIntlParser with data set #0 ('$1000.50', 100050)", "status": "pass", "time": 0.0069050788879395, "trace": [], @@ -333,12 +337,12 @@ "output": "" }{ "event": "testStart", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", - "test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)" + "suite": "Tests\\IntlMoneyParserTest::testIntlParser", + "test": "Tests\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)" }{ "event": "test", - "suite": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser", - "test": "Tests\\Money\\Parser\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)", + "suite": "Tests\\IntlMoneyParserTest::testIntlParser", + "test": "Tests\\IntlMoneyParserTest::testIntlParser with data set #1 ('$1000.00', 100000)", "status": "pass", "time": 0.00067996978759766, "trace": [], From f87cb40e6f251131e969f55d551259a1136cd5ad Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Tue, 18 Jul 2017 01:13:47 +0200 Subject: [PATCH 5/9] test PhpUnitResult with some output from test --- .../Plugin/SampleFiles/phpunit_money.txt | 15 ++++++++++++++- tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt index 1fa3e178..a28f7ec1 100644 --- a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt +++ b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt @@ -157,7 +157,7 @@ } ], "message": "Failed asserting that false is true.", - "output": "" + "output": "some output\nfrom f4" }{ "event": "suiteStart", "suite": "ExampleResults\\ExampleFailuresTest::testFailure5", @@ -301,6 +301,19 @@ "trace": [], "message": "Skipped Test: This test depends on \"ExampleResults\\ExampleFailuresTest::testFailure\" to pass.", "output": "" +}{ + "event": "testStart", + "suite": "", + "test": "ExampleResults\\ExampleFailuresTest::testOutput" +}{ + "event": "test", + "suite": "", + "test": "ExampleResults\\ExampleFailuresTest::testOutput", + "status": "pass", + "time": 0.0065488815307617, + "trace": [], + "message": "", + "output": "has output\non lines" }{ "event": "testStart", "suite": "Tests\\Money\\MoneyTest", diff --git a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php index 6cd864cf..d297343c 100644 --- a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php +++ b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php @@ -31,6 +31,9 @@ class PhpUnitResultTest extends \PHPUnit_Framework_TestCase $this->assertStringStartsNotWith($buildPath, $output[3]['trace'][0]); $this->assertStringStartsNotWith($buildPath, $output[3]['trace'][1]); + $this->assertEquals("some output\nfrom f4", $output[7]['output']); + $this->assertEquals("has output\non lines", $output[15]['output']); + $this->assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[5]['severity']); $this->assertContains('Incomplete Test:', $output[5]['message']); From 2bd6ae96cb720892d28b8391e655254b9cfdd48d Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Mon, 17 Jul 2017 21:26:32 +0200 Subject: [PATCH 6/9] add junit format for PhpUnitResult --- src/PHPCensor/Plugin/Util/PhpUnitResult.php | 2 + .../Plugin/Util/PhpUnitResultJunit.php | 130 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/PHPCensor/Plugin/Util/PhpUnitResultJunit.php diff --git a/src/PHPCensor/Plugin/Util/PhpUnitResult.php b/src/PHPCensor/Plugin/Util/PhpUnitResult.php index 10ef2fa1..d412cda5 100644 --- a/src/PHPCensor/Plugin/Util/PhpUnitResult.php +++ b/src/PHPCensor/Plugin/Util/PhpUnitResult.php @@ -13,6 +13,8 @@ abstract class PhpUnitResult const SEVERITY_FAIL = 'fail'; const SEVERITY_ERROR = 'error'; const SEVERITY_SKIPPED = 'skipped'; + const SEVERITY_WARN = self::SEVERITY_PASS; + const SEVERITY_RISKY = self::SEVERITY_PASS; protected $outputFile; protected $buildPath; diff --git a/src/PHPCensor/Plugin/Util/PhpUnitResultJunit.php b/src/PHPCensor/Plugin/Util/PhpUnitResultJunit.php new file mode 100644 index 00000000..3f41cb8f --- /dev/null +++ b/src/PHPCensor/Plugin/Util/PhpUnitResultJunit.php @@ -0,0 +1,130 @@ + + */ +class PhpUnitResultJunit extends PhpUnitResult +{ + /** + * Parse the results + * + * @return $this + * @throws \Exception If fails to parse the output + */ + public function parse() + { + $suites = simplexml_load_file($this->outputFile); + + // Reset the parsing variables + $this->results = []; + $this->errors = []; + $this->failures = 0; + + foreach ($suites->xpath('//testcase') as $testCase) { + $this->parseTestcase($testCase); + } + $suites['failures']; + $suites['errors']; + + return $this; + } + + protected function getSeverity($testCase) + { + $severity = self::SEVERITY_PASS; + foreach($testCase as $child) { + switch ($child->getName()) { + case 'failure': + $severity = self::SEVERITY_FAIL; + break 2; + case 'error': + if ('PHPUnit\Framework\RiskyTestError' == $child['type']) { // == because convertion to string is desired + $severity = self::SEVERITY_RISKY; + } else { + $severity = self::SEVERITY_ERROR; + } + break 2; + case 'skipped': + // skipped and ignored, can not distinguish + $severity = self::SEVERITY_SKIPPED; + break 2; + case 'warning': + $severity = self::SEVERITY_WARN; + break 2; + case 'system-out': + case 'system-err': + // not results + continue; + default: + $severity = 'UNKNOWN RESULT TYPE: '.$child->getName(); + break 2; + } + } + + return $severity; + } + + protected function buildMessage($testCase) + { + $tracePos = -1; + $msg = $this->getMessageTrace($testCase); + if ('' !== $msg) { + //strip trace + $trPos = strrpos($msg, "\n\n"); + if (false !== $trPos) { + $tracePos = $trPos; + $msg = substr($msg, 0, $trPos); + } + } + if ('' === $msg) { + $msg = $testCase['class'].'::'.$testCase['name']; + }; + $testCase['_tracePos'] = $tracePos; // will be converted to string + + return $msg; + } + + protected function getOutput($testCase) { + return (string)$testCase->{'system-out'}; + } + + protected function buildTrace($testCase) + { + if (!is_int($testCase['_tracePos'])) { + $this->buildMessage($testCase); + } + + if ($testCase['_tracePos'] >= 0) { + $stackStr = substr($this->getMessageTrace($testCase), (int)$testCase['_tracePos'] + 2, -1); + $trace = explode("\n", str_replace($this->buildPath, '.', $stackStr)); + } else { + $trace = array(); + } + + return $trace; + } + + private function getMessageTrace($testCase) { + $msg = ''; + foreach($testCase as $child) { + switch ($child->getName()) { + case 'system-out': + case 'system-err': + // not results + continue; + default: + $msg = (string)$child['message']; // according to xsd + if ('' === $msg) { + $msg = (string)$child; + } + break 2; + } + } + + return $msg; + } +} From c89a6e979c26d5bc93e44da3c3298a8a4974de52 Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Mon, 17 Jul 2017 21:26:59 +0200 Subject: [PATCH 7/9] test PhpUnitResultJunit Test data is generated by real test suite, with phpunit 6.2 --- .../SampleFiles/phpunit_money_junit.xml | 133 ++++++++++++++++++ .../Plugin/Util/PhpUnitResultTest.php | 56 +++++++- 2 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/PHPCensor/Plugin/SampleFiles/phpunit_money_junit.xml diff --git a/tests/PHPCensor/Plugin/SampleFiles/phpunit_money_junit.xml b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money_junit.xml new file mode 100644 index 00000000..ba05f27e --- /dev/null +++ b/tests/PHPCensor/Plugin/SampleFiles/phpunit_money_junit.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + ExampleResults\ExampleFailuresTest::testFailure +InvalidArgumentException: Division by zero + +/path/to/build/src/Money.php:320 +/path/to/build/tests/ExampleFailuresTest.php:15 + + + + ExampleResults\ExampleFailuresTest::testFailure2 +Failed asserting that two objects are equal. +--- Expected ++++ Actual +@@ @@ + Money\Money Object ( +- 'amount' => '2' ++ 'amount' => '3' + 'currency' => Money\Currency Object (...) + ) + +/path/to/build/tests/ExampleFailuresTest.php:20 + + + + + + + ExampleResults\ExampleFailuresTest::testFailure3 +Failed asserting that two arrays are equal. +--- Expected ++++ Actual +@@ @@ + Array ( ++ 0 => 3 ++ 1 => 33 + ) + +/path/to/build/tests/ExampleFailuresTest.php:30 + + + + ExampleResults\ExampleFailuresTest::testFailure4 +Failed asserting that false is true. + +/path/to/build/tests/ExampleFailuresTest.php:35 + +some output +from f4 + + + + ExampleResults\ExampleFailuresTest::testFailure5 with data set #0 (1, 2, 3, 4, 5, 6) +Failed asserting that 3 is identical to 1. + +/path/to/build/tests/ExampleFailuresTest.php:43 + + + + ExampleResults\ExampleFailuresTest::testFailure5 with data set #1 ('one', 'two', 'three', 'four', 'five', 'six') +Failed asserting that two strings are identical. +--- Expected ++++ Actual +@@ @@ +-'one' ++'three' + +/path/to/build/tests/ExampleFailuresTest.php:43 + + + + ExampleResults\ExampleFailuresTest::testFailure5 with data set #2 (array(1, 'one'), array(2, 'two'), array(3, 'three'), array(4, 'four'), array(5, 'five'), array(6, 'six')) +Failed asserting that Array &0 ( + 0 => 3 + 1 => 'three' +) is identical to Array &0 ( + 0 => 1 + 1 => 'one' +). + +/path/to/build/tests/ExampleFailuresTest.php:43 + + + + + + + + + + + + + + + + + + + has output +on lines + + + + + Warning +No tests found in class "ExampleResults\EmptyWillWarnTest". + + + + + + + + Risky Test + + + + Risky Test + + + + + + diff --git a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php index d297343c..710ee60e 100644 --- a/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php +++ b/tests/PHPCensor/Plugin/Util/PhpUnitResultTest.php @@ -4,6 +4,7 @@ namespace Tests\PHPCensor\Plugin\Util; use PHPCensor\Plugin\Util\PhpUnitResult; use PHPCensor\Plugin\Util\PhpUnitResultJson; +use PHPCensor\Plugin\Util\PhpUnitResultJunit; /** * Class PhpUnitResultTest parses the results for the PhpUnitV2 plugin @@ -13,11 +14,20 @@ use PHPCensor\Plugin\Util\PhpUnitResultJson; */ class PhpUnitResultTest extends \PHPUnit_Framework_TestCase { + /** + * Skipped test results + * + * @var array[] + */ + static $skipped = []; - public function testInitParse() + /** + * @dataProvider getTestData + */ + public function testInitParse($resultClass, $testFile) { $buildPath = '/path/to/build'; - $parser = new PhpUnitResultJson(ROOT_DIR . 'tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt', $buildPath); + $parser = new $resultClass(ROOT_DIR . $testFile, $buildPath); $output = $parser->parse()->getResults(); $errors = $parser->getErrors(); @@ -35,9 +45,47 @@ class PhpUnitResultTest extends \PHPUnit_Framework_TestCase $this->assertEquals("has output\non lines", $output[15]['output']); $this->assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[5]['severity']); - $this->assertContains('Incomplete Test:', $output[5]['message']); + try { + $this->assertContains('Incomplete Test:', $output[5]['message']); + } catch (\PHPUnit_Framework_ExpectationFailedException $e) { + self::$skipped[] = ['cls' => $resultClass, 'ex' => $e]; + } catch (\PHPUnit\Framework\ExpectationFailedException $e) { + self::$skipped[] = ['cls' => $resultClass, 'ex' => $e]; + } $this->assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[11]['severity']); - $this->assertContains('Skipped Test:', $output[11]['message']); + try { + $this->assertContains('Skipped Test:', $output[11]['message']); + } catch (\PHPUnit_Framework_ExpectationFailedException $e) { + self::$skipped[] = ['cls' => $resultClass, 'ex' => $e]; + } catch (\PHPUnit\Framework\ExpectationFailedException $e) { + self::$skipped[] = ['cls' => $resultClass, 'ex' => $e]; + } + } + + /** + * used as long as junit format does not provide message for skipped tests + */ + public function testSkippedAnything() + { + if (self::$skipped) { + $msg = "Skipped result tests:\n"; + foreach (self::$skipped as $skip) { + $exMsg = strstr((string)$skip['ex'], "\n", true); + if (false === $exMsg) { + $exMsg = (string)$skip['ex']; + } + $msg .= sprintf(" * %s: %s \n", $skip['cls'], $exMsg); + } + $this->markTestSkipped($msg); + } + } + + public static function getTestData() + { + return [ + 'json' => [PhpUnitResultJson::class, 'tests/PHPCensor/Plugin/SampleFiles/phpunit_money.txt'], + 'junit' => [PhpUnitResultJunit::class, 'tests/PHPCensor/Plugin/SampleFiles/phpunit_money_junit.xml'], + ]; } } From 173f785d61ec668b01dfe4530a767a8336149dae Mon Sep 17 00:00:00 2001 From: SimonHeimberg Date: Mon, 17 Jul 2017 23:09:54 +0200 Subject: [PATCH 8/9] use log-junit when log-json is not supported by phpunit use json as long as available, since junit does not list skipped tests before phpunit 6 --- src/PHPCensor/Plugin/PhpUnit.php | 39 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/PHPCensor/Plugin/PhpUnit.php b/src/PHPCensor/Plugin/PhpUnit.php index 0e143e04..0abf1d51 100644 --- a/src/PHPCensor/Plugin/PhpUnit.php +++ b/src/PHPCensor/Plugin/PhpUnit.php @@ -8,6 +8,7 @@ use PHPCensor\Model\Build; use PHPCensor\Model\BuildError; use PHPCensor\Plugin\Option\PhpUnitOptions; use PHPCensor\Plugin\Util\PhpUnitResultJson; +use PHPCensor\Plugin\Util\PhpUnitResultJunit; use PHPCensor\Plugin; use PHPCensor\ZeroConfigPluginInterface; @@ -79,18 +80,28 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface return false; } + $cmd = $this->builder->findBinary('phpunit'); + // run without logging + $ret = null; + $lastLine = exec($cmd.' --log-json . --version'); + if (false !== strpos($lastLine, '--log-json')) { + $logFormat = 'junit'; // --log-json is not supported + } else { + $logFormat = 'json'; + } + $success = []; // Run any directories if (!empty($directories)) { foreach ($directories as $directory) { - $success[] = $this->runConfig($directory, null); + $success[] = $this->runConfig($directory, null, $logFormat); } } else { // Run any config files if (!empty($xmlConfigFiles)) { foreach ($xmlConfigFiles as $configFile) { - $success[] = $this->runConfig($this->options->getTestsPath(), $configFile); + $success[] = $this->runConfig($this->options->getTestsPath(), $configFile, $logFormat); } } } @@ -103,17 +114,18 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface * * @param $directory * @param $configFile + * @param string $logFormat * * @return bool|mixed */ - protected function runConfig($directory, $configFile) + protected function runConfig($directory, $configFile, $logFormat) { $options = clone $this->options; $buildPath = $this->build->getBuildPath() . DIRECTORY_SEPARATOR; - // Save the results into a json file + // Save the results into a log file $logFile = @tempnam($buildPath, 'jLog_'); - $options->addArgument('log-json', $logFile); + $options->addArgument('log-'.$logFormat, $logFile); // Removes any current configurations files $options->removeArgument('configuration'); @@ -126,7 +138,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface $cmd = $this->findBinary('phpunit') . ' %s %s'; $success = $this->builder->executeCommand($cmd, $arguments, $directory); - $this->processResults($logFile); + $this->processResults($logFile, $logFormat); return $success; } @@ -134,14 +146,19 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface /** * Saves the test results * - * @param string $jsonFile + * @param string $logFile + * @param string $logFormat * - * @throws \Exception If the failed to parse the JSON file + * @throws \Exception If failed to parse the log file */ - protected function processResults($jsonFile) + protected function processResults($logFile, $logFormat) { - if (file_exists($jsonFile)) { - $parser = new PhpUnitResultJson($logFile, $this->build->getBuildPath()); + if (file_exists($logFile)) { + if ('json' === $logFormat) { + $parser = new PhpUnitResultJson($logFile, $this->build->getBuildPath()); + } else { + $parser = new PhpUnitResultJunit($logFile, $this->build->getBuildPath()); + } $this->build->storeMeta('phpunit-data', $parser->parse()->getResults()); $this->build->storeMeta('phpunit-errors', $parser->getFailures()); From a6ee2756f5e7ece20cfd6b2252c1a374fc178420 Mon Sep 17 00:00:00 2001 From: Dmitry Khomutov Date: Thu, 20 Jul 2017 21:32:22 +0700 Subject: [PATCH 9/9] Fix after rebase on fresh master. --- src/PHPCensor/Plugin/PhpUnit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PHPCensor/Plugin/PhpUnit.php b/src/PHPCensor/Plugin/PhpUnit.php index 0abf1d51..941ab965 100644 --- a/src/PHPCensor/Plugin/PhpUnit.php +++ b/src/PHPCensor/Plugin/PhpUnit.php @@ -80,7 +80,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface return false; } - $cmd = $this->builder->findBinary('phpunit'); + $cmd = $this->findBinary('phpunit'); // run without logging $ret = null; $lastLine = exec($cmd.' --log-json . --version'); @@ -121,7 +121,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface protected function runConfig($directory, $configFile, $logFormat) { $options = clone $this->options; - $buildPath = $this->build->getBuildPath() . DIRECTORY_SEPARATOR; + $buildPath = $this->build->getBuildPath(); // Save the results into a log file $logFile = @tempnam($buildPath, 'jLog_');