mirror of
https://github.com/pestphp/pest.git
synced 2026-07-21 17:10:03 +02:00
fix: report dataset provider errors as failing tests (#1749)
Errors raised while resolving a test's dataset (missing named dataset, throwing dataset closure) previously crashed the whole run. Now the data provider catches them, wraps them in a DatasetProviderError, and the test method rethrows the original throwable so the affected test fails cleanly with a non-zero exit code while other tests keep running.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class DatasetProviderError extends RuntimeException
|
||||
{
|
||||
public function __construct(Throwable $previous)
|
||||
{
|
||||
parent::__construct($previous->getMessage(), (int) $previous->getCode(), $previous);
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,7 @@ final class TestCaseFactory
|
||||
$classCode = <<<PHP
|
||||
namespace $namespace;
|
||||
|
||||
use Pest\Exceptions\DatasetProviderError as __PestDatasetProviderError;
|
||||
use Pest\Repositories\DatasetsRepository as __PestDatasets;
|
||||
use Pest\TestSuite as __PestTestSuite;
|
||||
|
||||
|
||||
@@ -235,6 +235,10 @@ final class TestCaseMethodFactory
|
||||
$attributesCode
|
||||
public function $methodName(...\$arguments)
|
||||
{
|
||||
if (count(\$arguments) === 1 && \$arguments[0] instanceof __PestDatasetProviderError) {
|
||||
throw \$arguments[0]->getPrevious() ?? \$arguments[0];
|
||||
}
|
||||
|
||||
return \$this->__runTest(
|
||||
\$this->__test,
|
||||
...\$arguments,
|
||||
@@ -261,7 +265,11 @@ final class TestCaseMethodFactory
|
||||
|
||||
public static function $dataProviderName()
|
||||
{
|
||||
return __PestDatasets::get(self::\$__filename, "$methodName");
|
||||
try {
|
||||
return __PestDatasets::get(self::\$__filename, "$methodName");
|
||||
} catch (\Throwable \$throwable) {
|
||||
return [[new __PestDatasetProviderError(\$throwable)]];
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
dataset('throws', function () {
|
||||
throw new RuntimeException('boom from dataset');
|
||||
});
|
||||
|
||||
it('x', function ($a) {
|
||||
expect($a)->toBeTrue();
|
||||
})->with('throws');
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
it('references a missing dataset', function ($value) {
|
||||
expect($value)->toBeTruthy();
|
||||
})->with('missing');
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
it('passes normally', function () {
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
it('references a missing dataset', function ($value) {
|
||||
expect($value)->toBeTruthy();
|
||||
})->with('missing');
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
$run = function (string $target): array {
|
||||
$process = new Process(
|
||||
['php', 'bin/pest', $target],
|
||||
dirname(__DIR__, 2),
|
||||
['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],
|
||||
);
|
||||
|
||||
$process->run();
|
||||
|
||||
return [
|
||||
'output' => removeAnsiEscapeSequences($process->getOutput().$process->getErrorOutput()),
|
||||
'code' => $process->getExitCode(),
|
||||
];
|
||||
};
|
||||
|
||||
test('reports missing datasets as errors for a single file run', function () use ($run) {
|
||||
$result = $run('tests/.tests/IssueOnly.php');
|
||||
|
||||
expect($result['output'])
|
||||
->toContain("A dataset with the name `missing` does not exist. You can create it using `dataset('missing', ['a', 'b']);`.")
|
||||
->toContain('FAILED')
|
||||
->toContain('Tests: 1 failed');
|
||||
|
||||
expect($result['code'])->not->toBe(0);
|
||||
})->skipOnWindows();
|
||||
|
||||
test('reports missing datasets as errors alongside passing tests', function () use ($run) {
|
||||
$result = $run('tests/.tests/IssueWithPassing.php');
|
||||
|
||||
expect($result['output'])
|
||||
->toContain("A dataset with the name `missing` does not exist. You can create it using `dataset('missing', ['a', 'b']);`.")
|
||||
->toContain('1 passed')
|
||||
->toContain('1 failed');
|
||||
|
||||
expect($result['code'])->not->toBe(0);
|
||||
})->skipOnWindows();
|
||||
|
||||
test('reports dataset closure exceptions as errors', function () use ($run) {
|
||||
$result = $run('tests/.tests/DatasetClosureThrows.php');
|
||||
|
||||
expect($result['output'])
|
||||
->toContain('boom from dataset');
|
||||
|
||||
expect($result['code'])->not->toBe(0);
|
||||
})->skipOnWindows();
|
||||
Reference in New Issue
Block a user