diff --git a/src/Helper/Xml.php b/src/Helper/Xml.php
new file mode 100644
index 00000000..e3b91876
--- /dev/null
+++ b/src/Helper/Xml.php
@@ -0,0 +1,85 @@
+data = preg_replace(self::PATTERN, '', $bucket->data);
+ $consumed += $bucket->datalen;
+
+ stream_bucket_append($out, $bucket);
+ }
+
+ return PSFS_PASS_ON;
+ }
+}
+
+class Xml
+{
+ /**
+ * @param $filePath
+ *
+ * @return null|\SimpleXMLElement
+ */
+ public static function loadFromFile($filePath)
+ {
+ stream_filter_register('xml_utf8_clean', 'PHPCensor\Helper\XmlUtf8CleanFilter');
+
+ try {
+ $xml = simplexml_load_file('php://filter/read=xml_utf8_clean/resource=' . $filePath);
+ } catch (\Exception $ex) {
+ $xml = null;
+ } catch (\Throwable $ex) { // since php7
+ $xml = null;
+ }
+
+ if (!$xml) {
+ // from https://stackoverflow.com/questions/7766455/how-to-handle-invalid-unicode-with-simplexml/8092672#8092672
+ $oldUse = libxml_use_internal_errors(true);
+
+ libxml_clear_errors();
+
+ $dom = new \DOMDocument("1.0", "UTF-8");
+
+ $dom->strictErrorChecking = false;
+ $dom->validateOnParse = false;
+ $dom->recover = true;
+
+ $dom->loadXML(strtr(
+ file_get_contents($filePath),
+ ['"' => "'"] // " in attribute names may mislead the parser
+ ));
+
+ /** @var \LibXMLError $xmlError */
+ $xmlError = libxml_get_last_error();
+ if ($xmlError) {
+ $warning = sprintf('L%s C%s: %s', $xmlError->line, $xmlError->column, $xmlError->message);
+ print 'WARNING: ignored errors while reading phpunit result, '.$warning."\n";
+ }
+
+ if (!$dom->hasChildNodes()) {
+ new \SimpleXMLElement('');
+ }
+
+ $xml = simplexml_import_dom($dom);
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($oldUse);
+ }
+
+ return $xml;
+ }
+}
diff --git a/src/Plugin/Codeception.php b/src/Plugin/Codeception.php
index d5e8e1d4..585aea4e 100644
--- a/src/Plugin/Codeception.php
+++ b/src/Plugin/Codeception.php
@@ -145,8 +145,7 @@ class Codeception extends Plugin implements ZeroConfigPluginInterface
}
}
- $xml = file_get_contents($outputPath . 'report.xml', false);
- $parser = new Parser($this->builder, $xml);
+ $parser = new Parser($this->builder, ($outputPath . 'report.xml'));
$output = $parser->parse();
$meta = [
diff --git a/src/Plugin/Util/PhpUnitResultJunit.php b/src/Plugin/Util/PhpUnitResultJunit.php
index 3e149105..14ec1c7f 100644
--- a/src/Plugin/Util/PhpUnitResultJunit.php
+++ b/src/Plugin/Util/PhpUnitResultJunit.php
@@ -2,6 +2,8 @@
namespace PHPCensor\Plugin\Util;
+use PHPCensor\Helper\Xml;
+
/**
* Class PhpUnitResultJunit parses the results for the PhpUnitV2 plugin
*
@@ -24,11 +26,11 @@ class PhpUnitResultJunit extends PhpUnitResult
$suites = $this->loadResultFile();
- foreach ($suites->xpath('//testcase') as $testCase) {
- $this->parseTestcase($testCase);
+ if ($suites) {
+ foreach ($suites->xpath('//testcase') as $testCase) {
+ $this->parseTestcase($testCase);
+ }
}
- $suites['failures'];
- $suites['errors'];
return $this;
}
@@ -139,44 +141,7 @@ class PhpUnitResultJunit extends PhpUnitResult
return new \SimpleXMLElement(''); // new empty element
}
- try {
- $suites = simplexml_load_file($this->outputFile);
- } catch (\Exception $ex) {
- $suites = null;
- } catch (\Throwable $ex) { // since php7
- $suites = null;
- }
- if (!$suites) {
- // from https://stackoverflow.com/questions/7766455/how-to-handle-invalid-unicode-with-simplexml/8092672#8092672
- $oldUse = libxml_use_internal_errors(true);
- libxml_clear_errors();
- $dom = new \DOMDocument("1.0", "UTF-8");
- $dom->strictErrorChecking = false;
- $dom->validateOnParse = false;
- $dom->recover = true;
- $dom->loadXML(strtr(
- file_get_contents($this->outputFile),
- array('"' => "'") // " in attribute names may mislead the parser
- ));
-
- /**
- * @var \LibXMLError
- */
- $xmlError = libxml_get_last_error();
- if ($xmlError) {
- $warning = sprintf('L%s C%s: %s', $xmlError->line, $xmlError->column, $xmlError->message);
- print 'WARNING: ignored errors while reading phpunit result, '.$warning."\n";
- }
- if (!$dom->hasChildNodes()) {
- $this->internalProblem('xml file with no content');
- }
- $suites = simplexml_import_dom($dom);
-
- libxml_clear_errors();
- libxml_use_internal_errors($oldUse);
- }
-
- return $suites;
+ return Xml::loadFromFile($this->outputFile);
}
/**
@@ -185,7 +150,5 @@ class PhpUnitResultJunit extends PhpUnitResult
private function internalProblem($description)
{
throw new \RuntimeException($description);
-
- // alternative to error throwing: append to $this->errors
}
}
diff --git a/src/Plugin/Util/TestResultParsers/Codeception.php b/src/Plugin/Util/TestResultParsers/Codeception.php
index dfd97cae..90fcbb2e 100644
--- a/src/Plugin/Util/TestResultParsers/Codeception.php
+++ b/src/Plugin/Util/TestResultParsers/Codeception.php
@@ -3,6 +3,7 @@
namespace PHPCensor\Plugin\Util\TestResultParsers;
use PHPCensor\Builder;
+use PHPCensor\Helper\Xml;
/**
* Class Codeception
@@ -11,23 +12,49 @@ use PHPCensor\Builder;
*/
class Codeception implements ParserInterface
{
+ /**
+ * @var Builder
+ */
protected $builder;
- protected $resultsXml;
+
+ /**
+ * @var string
+ */
+ protected $xmlPath;
+
+ /**
+ * @var array
+ */
protected $results;
- protected $totalTests;
- protected $totalTimeTaken;
- protected $totalFailures;
- protected $totalErrors;
+
+ /**
+ * @var int
+ */
+ protected $totalTests = 0;
+
+ /**
+ * @var int
+ */
+ protected $totalTimeTaken = 0;
+
+ /**
+ * @var int
+ */
+ protected $totalFailures = 0;
+
+ /**
+ * @var int
+ */
+ protected $totalErrors = 0;
/**
* @param Builder $builder
- * @param $resultsXml
+ * @param string $xmlPath
*/
- public function __construct(Builder $builder, $resultsXml)
+ public function __construct(Builder $builder, $xmlPath)
{
- $this->builder = $builder;
- $this->resultsXml = $resultsXml;
- $this->totalTests = 0;
+ $this->builder = $builder;
+ $this->xmlPath = $xmlPath;
}
/**
@@ -36,42 +63,43 @@ class Codeception implements ParserInterface
public function parse()
{
$rtn = [];
- $this->results = new \SimpleXMLElement($this->resultsXml);
+ $this->results = Xml::loadFromFile($this->xmlPath);
- // calculate total results
- foreach ($this->results->testsuite as $testSuite) {
- $this->totalTests += (int)$testSuite['tests'];
- $this->totalTimeTaken += (float)$testSuite['time'];
- $this->totalFailures += (int)$testSuite['failures'];
- $this->totalErrors += (int)$testSuite['errors'];
+ if ($this->results) {
+ foreach ($this->results->testsuite as $testSuite) {
+ $this->totalTests += (int)$testSuite['tests'];
+ $this->totalTimeTaken += (float)$testSuite['time'];
+ $this->totalFailures += (int)$testSuite['failures'];
+ $this->totalErrors += (int)$testSuite['errors'];
- foreach ($testSuite->testcase as $testCase) {
- $testResult = [
- 'suite' => (string)$testSuite['name'],
- 'file' => str_replace($this->builder->buildPath, '/', (string) $testCase['file']),
- 'name' => (string)$testCase['name'],
- 'feature' => (string)$testCase['feature'],
- 'assertions' => (int)$testCase['assertions'],
- 'time' => (float)$testCase['time']
- ];
+ foreach ($testSuite->testcase as $testCase) {
+ $testResult = [
+ 'suite' => (string)$testSuite['name'],
+ 'file' => str_replace($this->builder->buildPath, '/', (string) $testCase['file']),
+ 'name' => (string)$testCase['name'],
+ 'feature' => (string)$testCase['feature'],
+ 'assertions' => (int)$testCase['assertions'],
+ 'time' => (float)$testCase['time']
+ ];
- if (isset($testCase['class'])) {
- $testResult['class'] = (string) $testCase['class'];
+ if (isset($testCase['class'])) {
+ $testResult['class'] = (string) $testCase['class'];
+ }
+
+ // PHPUnit testcases does not have feature field. Use class::method instead
+ if (!$testResult['feature']) {
+ $testResult['feature'] = sprintf('%s::%s', $testResult['class'], $testResult['name']);
+ }
+
+ if (isset($testCase->failure) || isset($testCase->error)) {
+ $testResult['pass'] = false;
+ $testResult['message'] = isset($testCase->failure) ? (string)$testCase->failure : (string)$testCase->error;
+ } else {
+ $testResult['pass'] = true;
+ }
+
+ $rtn[] = $testResult;
}
-
- // PHPUnit testcases does not have feature field. Use class::method instead
- if (!$testResult['feature']) {
- $testResult['feature'] = sprintf('%s::%s', $testResult['class'], $testResult['name']);
- }
-
- if (isset($testCase->failure) || isset($testCase->error)) {
- $testResult['pass'] = false;
- $testResult['message'] = isset($testCase->failure) ? (string)$testCase->failure : (string)$testCase->error;
- } else {
- $testResult['pass'] = true;
- }
-
- $rtn[] = $testResult;
}
}