From a4a807e2cec844ba650473acb18a3055a0472965 Mon Sep 17 00:00:00 2001 From: Ewout Pieter den Ouden Date: Fri, 11 Jan 2019 14:35:55 +0100 Subject: [PATCH] Add code location hints from plain PHPT exception messages --- src/Framework/Assert.php | 1 + src/Runner/PhptTestCase.php | 46 +++++++++++++++++-- .../end-to-end/phpt/expect-location-hint.phpt | 2 +- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/Framework/Assert.php b/src/Framework/Assert.php index 4b08f1161e8..1312499dbf9 100644 --- a/src/Framework/Assert.php +++ b/src/Framework/Assert.php @@ -3002,6 +3002,7 @@ public static function markTestSkipped(string $message = ''): void { if ($hint = self::detectLocationHint($message)) { $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); + \array_unshift($trace, $hint); throw new SyntheticSkippedError($hint['message'], 0, $hint['file'], $hint['line'], $trace); } diff --git a/src/Runner/PhptTestCase.php b/src/Runner/PhptTestCase.php index 5341c677178..cac1124eb80 100644 --- a/src/Runner/PhptTestCase.php +++ b/src/Runner/PhptTestCase.php @@ -178,9 +178,15 @@ public function run(TestResult $result = null): TestResult if ($xfail !== false) { $failure = new IncompleteTestError($xfail, 0, $e); } else { - if ($e instanceof ExpectationFailedException && $e->getComparisonFailure()) { + if ($e instanceof ExpectationFailedException) { /** @var ExpectationFailedException $e */ - $hint = $this->getLocationHintFromDiff($e->getComparisonFailure()->getDiff(), $sections); + if ($e->getComparisonFailure()) { + $diff = $e->getComparisonFailure()->getDiff(); + } else { + $diff = $e->getMessage(); + } + + $hint = $this->getLocationHintFromDiff($diff, $sections); $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); \array_unshift($trace, $hint); $failure = new PHPTAssertionFailedError($e->getMessage(), 0, $trace[0]['file'], $trace[0]['line'], $trace); @@ -608,14 +614,44 @@ private function stringifyIni(array $ini): array private function getLocationHintFromDiff(string $message, array $sections): array { $needle = ''; + $previousLine = ''; + $block = 'message'; - if (\preg_match("/--- Expected[^']+^-'([^']*)'/m", $message, $matches)) { - $needle = $matches[1]; - } + foreach (explode(\PHP_EOL, $message) as $line) { + $line = \trim($line); + if ($block === 'message' && $line === '--- Expected') { + $block = 'expected'; + } + if ($block === 'expected' && $line === '@@ @@') { + $block = 'diff'; + } + + if ($block === 'diff') { + if (substr($line, 0, 1) === '+') { + $needle = $this->getCleanDiffLine($previousLine); + break; + } elseif (substr($line, 0, 1) === '-') { + $needle = $this->getCleanDiffLine($line); + break; + } + } + if (!empty($line)) { + $previousLine = $line; + } + } return $this->getLocationHint($needle, $sections); } + private function getCleanDiffLine(string $line): string + { + if (\preg_match('/^[\-+]([\'\"]?)(.*)\1$/', $line, $matches)) { + $line = $matches[2]; + } + + return $line; + } + private function getLocationHint(string $needle, array $sections, ?string $sectionName = null): array { $needle = \trim($needle); diff --git a/tests/end-to-end/phpt/expect-location-hint.phpt b/tests/end-to-end/phpt/expect-location-hint.phpt index 8a97c4c0258..f2a49f56588 100644 --- a/tests/end-to-end/phpt/expect-location-hint.phpt +++ b/tests/end-to-end/phpt/expect-location-hint.phpt @@ -1,5 +1,5 @@ --TEST-- -PHPT skip condition results in correct code location hint +PHPT EXPECT comparison returns correct code location hint --FILE--