Skip to content

Commit

Permalink
Differentiate parsing errors in a parent class from the ones in the t…
Browse files Browse the repository at this point in the history
…est class
  • Loading branch information
martin-rueegg committed Aug 20, 2023
1 parent 641efdd commit bf54a50
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 4 deletions.
2 changes: 2 additions & 0 deletions composer.json
Expand Up @@ -90,6 +90,8 @@
"tests/data/register_command/examples",
"tests/data/DummyClass.php",
"tests/data/DummyOverloadableClass.php",
"tests/data/InvalidClass.php",
"tests/data/InvalidChildClass.php",
"tests/data/services/UserModel.php",
"tests/data/services/UserService.php",
"tests/unit/Codeception/Command/BaseCommandRunner.php",
Expand Down
13 changes: 11 additions & 2 deletions src/Codeception/Exception/TestParseException.php
Expand Up @@ -8,14 +8,23 @@

class TestParseException extends Exception
{
public function __construct(string $fileName, string $errors = null, int $line = null)
public function __construct(string $fileName, string $errors = null, int $line = null, string $testFile = null)
{
$fileName = self::normalizePathSeparators($fileName);
$this->message = "Couldn't parse test '{$fileName}'";
if ($line !== null) {
$this->message .= " on line {$line}";
}
if ($errors) {
$this->message .= PHP_EOL . $errors;
$this->message .= ":" . PHP_EOL . $errors;
}
if (($testFile = self::normalizePathSeparators($testFile)) && realpath($fileName) !== realpath($testFile)) {
$this->message .= PHP_EOL . "(Error occurred while parsing Test '{$testFile}')";
}
}

public static function normalizePathSeparators(?string $testFile): ?string
{
return str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $testFile ?? '');
}
}
2 changes: 1 addition & 1 deletion src/Codeception/Lib/Parser.php
Expand Up @@ -100,7 +100,7 @@ public static function load(string $file): void
try {
self::includeFile($file);
} catch (ParseError $e) {
throw new TestParseException($file, $e->getMessage(), $e->getLine());
throw new TestParseException($e->getFile(), $e->getMessage(), $e->getLine(), $file);
} catch (Exception) {
// file is valid otherwise
}
Expand Down
5 changes: 5 additions & 0 deletions tests/data/InvalidChildClass.php
@@ -0,0 +1,5 @@
<?php

class InvalidChildClass extends InvalidClass
{
}
6 changes: 6 additions & 0 deletions tests/data/InvalidClass.php
@@ -0,0 +1,6 @@
<?php

class InvalidClass
{
foo
}
76 changes: 75 additions & 1 deletion tests/unit/Codeception/Lib/ParserTest.php
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Codeception\Attribute\Group;
use Codeception\Exception\TestParseException;
use Codeception\Lib\Parser;
use Codeception\Scenario;
use Codeception\Test\Cept;
Expand Down Expand Up @@ -146,13 +147,86 @@ public function testParseFileWhichUnsetsFileVariable()
$this->assertSame([], $classes);
}

#[Group('core')]
public function testParseExceptionWithFileNameOnly()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage("Couldn't parse test 'test.file'");
throw new TestParseException('test.file');
}

#[Group('core')]
public function testParseExceptionWithErrors()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage("Couldn't parse test 'test.file':" . PHP_EOL . "Funny error");
throw new TestParseException('test.file', 'Funny error');
}

#[Group('core')]
public function testParseExceptionWithLineNumber()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage("Couldn't parse test 'test.file' on line 27:" . PHP_EOL . "Funny error");
throw new TestParseException('test.file', 'Funny error', 27);
}

#[Group('core')]
public function testParseExceptionWithTestFile()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage("Couldn't parse test 'test.file' on line 27:" . PHP_EOL . "Funny error" . PHP_EOL . "(Error occurred while parsing Test 'test.file')");
throw new TestParseException('test.file', 'Funny error', 27, 'test.file');
}

#[Group('core')]
public function testParseExceptionWithDifferentTestFile()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage(sprintf(
"Couldn't parse test '%s' on line %d:" . PHP_EOL . "%s" . PHP_EOL . "(Error occurred while parsing Test '%s')",
'parent.file',
27,
'Funny error',
'test.file'
));
throw new TestParseException('parent.file', 'Funny error', 27, 'test.file');
}

#[Group('core')]
public function testModernValidation()
{
$this->expectException(\Codeception\Exception\TestParseException::class);
$this->expectException(TestParseException::class);
Parser::load(codecept_data_dir('Invalid.php'));
}

#[Group('core')]
public function testModernClassValidation()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage(sprintf(
"Couldn't parse test '%s' on line %d:" . PHP_EOL . "%s",
TestParseException::normalizePathSeparators(codecept_data_dir('InvalidClass.php')),
5,
'syntax error, unexpected identifier "foo", expecting "function" or "const"'
));
Parser::load(codecept_data_dir('InvalidClass.php'));
}

#[Group('core')]
public function testModernChildClassValidation()
{
$this->expectException(TestParseException::class);
$this->expectExceptionMessage(sprintf(
"Couldn't parse test '%s' on line %d:" . PHP_EOL . "%s" . PHP_EOL . "(Error occurred while parsing Test '%s')",
TestParseException::normalizePathSeparators(codecept_data_dir('InvalidClass.php')),
5,
'syntax error, unexpected identifier "foo", expecting "function" or "const"',
TestParseException::normalizePathSeparators(codecept_data_dir('InvalidChildClass.php'))
));
Parser::load(codecept_data_dir('InvalidChildClass.php'));
}

#[Group('core')]
public function testClassesFromFile()
{
Expand Down

0 comments on commit bf54a50

Please sign in to comment.