diff --git a/src/Plugin/PhpUnit.php b/src/Plugin/PhpUnit.php index f7988b2e..d45b347d 100644 --- a/src/Plugin/PhpUnit.php +++ b/src/Plugin/PhpUnit.php @@ -42,10 +42,8 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface */ protected $buildBranchLocation; - /** - * @var string[] Raw options from the config file - */ - protected $options = []; + /** @var PhpUnitOptions*/ + protected $options; /** * @return string @@ -83,7 +81,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface /** * Check if the plugin can be executed without any configurations * - * @param $stage + * @param string $stage * @param Builder $builder * @param Build $build * @@ -140,9 +138,9 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface /** * Run the tests defined in a PHPUnit config file or in a specific directory. * - * @param $directory - * @param $configFile - * @param string $logFormat + * @param string $directory + * @param string|null $configFile + * @param string $logFormat * * @return bool|mixed * diff --git a/src/Plugin/Util/PhpUnitResultJunit.php b/src/Plugin/Util/PhpUnitResultJunit.php index 3f41cb8f..c16a4ebc 100644 --- a/src/Plugin/Util/PhpUnitResultJunit.php +++ b/src/Plugin/Util/PhpUnitResultJunit.php @@ -17,13 +17,13 @@ class PhpUnitResultJunit extends PhpUnitResult */ public function parse() { - $suites = simplexml_load_file($this->outputFile); - // Reset the parsing variables $this->results = []; $this->errors = []; $this->failures = 0; + $suites = $this->loadResultFile(); + foreach ($suites->xpath('//testcase') as $testCase) { $this->parseTestcase($testCase); } @@ -127,4 +127,62 @@ class PhpUnitResultJunit extends PhpUnitResult return $msg; } + + /** + * @return \SimpleXMLElement + */ + private function loadResultFile() + { + if (!file_exists($this->outputFile) || 0 === filesize($this->outputFile)) { + $this->internalProblem('empty output file'); + + 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; + } + + private function internalProblem($description) + { + throw new \Exception($description); + + // alternative to error throwing: append to $this->errors + } }