From 3ee0f473a33fa2586dce683708a43343b2c775fd Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Mon, 7 Oct 2024 16:25:59 +0200 Subject: [PATCH 01/11] Save names of data providers for better debug message and possibility of more generic tests --- src/Framework/Exception/Exception.php | 4 +- src/Framework/TestBuilder.php | 27 ++-- src/Framework/TestCase.php | 23 ++++ src/Framework/TestSuite.php | 3 +- src/Metadata/Api/DataProvider.php | 125 +++++++++-------- ...bstractVariousIterableDataProviderTest.php | 6 +- tests/unit/Metadata/Api/DataProviderTest.php | 126 ++++++------------ 7 files changed, 154 insertions(+), 160 deletions(-) diff --git a/src/Framework/Exception/Exception.php b/src/Framework/Exception/Exception.php index e35b0d50520..7bf7600257b 100644 --- a/src/Framework/Exception/Exception.php +++ b/src/Framework/Exception/Exception.php @@ -46,8 +46,9 @@ class Exception extends RuntimeException implements \PHPUnit\Exception * @var list */ protected array $serializableTrace; + public ?string $method; - public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null) + public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null, ?string $method = null) { /** * @see https://github.com/sebastianbergmann/phpunit/issues/5965 @@ -68,6 +69,7 @@ public function __construct(string $message = '', int|string $code = 0, ?Throwab foreach (array_keys($this->serializableTrace) as $key) { unset($this->serializableTrace[$key]['args']); } + $this->method = $method; } public function __sleep(): array diff --git a/src/Framework/TestBuilder.php b/src/Framework/TestBuilder.php index 5c3effc7a35..5f20d39e5d4 100644 --- a/src/Framework/TestBuilder.php +++ b/src/Framework/TestBuilder.php @@ -47,7 +47,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou $data = (new DataProvider)->providedData($className, $methodName); } - if ($data !== null) { + if ($data !== null && reset($data) !== null) { return $this->buildDataProviderTestSuite( $methodName, $className, @@ -91,20 +91,23 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam (new Groups)->groups($className, $methodName), ); - foreach ($data as $_dataName => $_data) { - $_test = new $className($methodName); + foreach ($data as $providerName => $providedData){ + foreach ($providedData as $_dataName => $_data){ + $_test = new $className($methodName); - $_test->setData($_dataName, $_data); + $_test->setData($_dataName, $_data); - $this->configureTestCase( - $_test, - $runTestInSeparateProcess, - $preserveGlobalState, - $runClassInSeparateProcess, - $backupSettings, - ); + $this->configureTestCase( + $_test, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings, + ); - $dataProviderTestSuite->addTest($_test, $groups); + $_test->setProviderName($providerName); + $dataProviderTestSuite->addTest($_test, $groups); + } } return $dataProviderTestSuite; diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 2d749ea2433..23da682955c 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -146,6 +146,11 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T */ private string $methodName; + /** + * @var non-empty-string + */ + protected string $providerName; + /** * @var list */ @@ -360,6 +365,24 @@ final public function setGroups(array $groups): void $this->groups = $groups; } + /** + * @return string + */ + public function getProviderName(): string + { + return $this->providerName; + } + + /** + * @param string $providerName + * @return $this + */ + public function setProviderName(string $providerName): TestCase + { + $this->providerName = $providerName; + return $this; + } + /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ diff --git a/src/Framework/TestSuite.php b/src/Framework/TestSuite.php index daf44a98643..41e5175997d 100644 --- a/src/Framework/TestSuite.php +++ b/src/Framework/TestSuite.php @@ -527,7 +527,8 @@ protected function addTestMethod(ReflectionClass $class, ReflectionMethod $metho Event\TestData\TestDataCollection::fromArray([]), ), sprintf( - "The data provider specified for %s::%s is invalid\n%s", + "The data provider %s specified for %s::%s is invalid\n%s", + $e->method, $className, $methodName, $this->throwableToString($e), diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 1f3c1e6ca4f..61a4b1e9c96 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -30,6 +30,7 @@ use function substr; use function trim; use PHPUnit\Event; +use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Framework\InvalidDataProviderException; use PHPUnit\Metadata\DataProvider as DataProviderMetadata; use PHPUnit\Metadata\MetadataCollection; @@ -60,30 +61,32 @@ public function providedData(string $className, string $methodName): ?array $testWith = MetadataRegistry::parser()->forMethod($className, $methodName)->isTestWith(); if ($dataProvider->isEmpty() && $testWith->isEmpty()) { - return $this->dataProvidedByTestWithAnnotation($className, $methodName); + return ['testWith' => $this->dataProvidedByTestWithAnnotation($className, $methodName)]; } if ($dataProvider->isNotEmpty()) { $data = $this->dataProvidedByMethods($className, $methodName, $dataProvider); } else { - $data = $this->dataProvidedByMetadata($testWith); + $data = ['testWith' => $this->dataProvidedByMetadata($testWith)]; } - if ($data === []) { + if ($data === [] || $data === ['testWith' => []]) { throw new InvalidDataProviderException( 'Empty data set provided by data provider', ); } - foreach ($data as $key => $value) { - if (!is_array($value)) { - throw new InvalidDataProviderException( - sprintf( - 'Data set %s is invalid, expected array but got %s', - is_int($key) ? '#' . $key : '"' . $key . '"', - get_debug_type($value), - ), - ); + foreach ($data as $providedData) { + foreach ($providedData as $key => $value) { + if (!is_array($value)) { + throw new InvalidDataProviderException( + sprintf( + 'Data set %s is invalid, expected array but got %s', + is_int($key) ? '#' . $key : '"' . $key . '"', + get_debug_type($value), + ), + ); + } } } @@ -91,23 +94,26 @@ public function providedData(string $className, string $methodName): ?array } /** - * @param class-string $className - * @param non-empty-string $methodName + * @param class-string $testClassName Name of class with test + * @param non-empty-string $testMethodName Name of method containing test * * @throws InvalidDataProviderException * * @return array> */ - private function dataProvidedByMethods(string $className, string $methodName, MetadataCollection $dataProvider): array + private function dataProvidedByMethods(string $testClassName, string $testMethodName, MetadataCollection $dataProvider): array { - $testMethod = new Event\Code\ClassMethod($className, $methodName); + $testMethod = new ClassMethod($testClassName, $testMethodName); $methodsCalled = []; - $result = []; + $return = []; + $caseNames = []; foreach ($dataProvider as $_dataProvider) { assert($_dataProvider instanceof DataProviderMetadata); - $dataProviderMethod = new Event\Code\ClassMethod($_dataProvider->className(), $_dataProvider->methodName()); + $providerClassName = $_dataProvider->className(); + $providerMethodName = $_dataProvider->methodName(); + $dataProviderMethod = new ClassMethod($providerClassName, $providerMethodName); Event\Facade::emitter()->dataProviderMethodCalled( $testMethod, @@ -117,65 +123,42 @@ private function dataProvidedByMethods(string $className, string $methodName, Me $methodsCalled[] = $dataProviderMethod; try { - $class = new ReflectionClass($_dataProvider->className()); - $method = $class->getMethod($_dataProvider->methodName()); + $class = new ReflectionClass($providerClassName); + $method = $class->getMethod($providerMethodName); if (!$method->isPublic()) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() is not public', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('is not public', $_dataProvider); } if (!$method->isStatic()) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() is not static', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('is not static', $_dataProvider); } if ($method->getNumberOfParameters() > 0) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() expects an argument', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('expects an argument', $_dataProvider); } - $className = $_dataProvider->className(); - $methodName = $_dataProvider->methodName(); - $data = $className::$methodName(); + $data = $providerClassName::$providerMethodName(); + if (!is_iterable($data)) { + $this->throwInvalid('does not provide iterable type', $_dataProvider); + } } catch (Throwable $e) { - Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, - ...$methodsCalled, - ); - + $this->finishMethods($testMethod, $methodsCalled); throw new InvalidDataProviderException( $e->getMessage(), $e->getCode(), $e, + $providerMethodName ); } + $result = []; foreach ($data as $key => $value) { if (is_int($key)) { $result[] = $value; } elseif (is_string($key)) { - if (array_key_exists($key, $result)) { - Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, - ...$methodsCalled, - ); - + if (isset($caseNames[$key])) { + $this->finishMethods($testMethod, $methodsCalled); throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous data provider', @@ -183,7 +166,7 @@ private function dataProvidedByMethods(string $className, string $methodName, Me ), ); } - + $caseNames[$key] = 1; $result[$key] = $value; } else { throw new InvalidDataProviderException( @@ -194,14 +177,38 @@ private function dataProvidedByMethods(string $className, string $methodName, Me ); } } + $return[$providerMethodName] = $result; } + $this->finishMethods($testMethod, $methodsCalled); + + return $return; + } + /** + * @param string $message + * @param DataProviderMetadata $dataProvider + * @return never + */ + private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never { + throw new InvalidDataProviderException( + sprintf( + 'Data Provider method %s::%s() ', + $dataProvider->className(), + $dataProvider->methodName(), + ) . $message, + ); + } + + /** + * @param ClassMethod $method + * @param array $methodsCalled + * @return void + */ + private function finishMethods(ClassMethod $method, array $methodsCalled): void { Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, + $method, ...$methodsCalled, ); - - return $result; } /** diff --git a/tests/_files/AbstractVariousIterableDataProviderTest.php b/tests/_files/AbstractVariousIterableDataProviderTest.php index d2d390e8d43..95ba6d8f214 100644 --- a/tests/_files/AbstractVariousIterableDataProviderTest.php +++ b/tests/_files/AbstractVariousIterableDataProviderTest.php @@ -13,7 +13,7 @@ abstract class AbstractVariousIterableDataProviderTest { - public static function asArrayProviderInParent() + public static function asArrayProviderInParent(): array { return [ ['J'], @@ -22,7 +22,7 @@ public static function asArrayProviderInParent() ]; } - public static function asIteratorProviderInParent() + public static function asIteratorProviderInParent(): \Generator { yield ['M']; @@ -31,7 +31,7 @@ public static function asIteratorProviderInParent() yield ['O']; } - public static function asTraversableProviderInParent() + public static function asTraversableProviderInParent(): WrapperIteratorAggregate { return new WrapperIteratorAggregate([ ['P'], diff --git a/tests/unit/Metadata/Api/DataProviderTest.php b/tests/unit/Metadata/Api/DataProviderTest.php index 442b58cd8be..ea4ac6eef86 100644 --- a/tests/unit/Metadata/Api/DataProviderTest.php +++ b/tests/unit/Metadata/Api/DataProviderTest.php @@ -30,44 +30,12 @@ final class DataProviderTest extends TestCase */ public function testMultipleDataProviders(): void { - $dataSets = (new DataProvider)->providedData(MultipleDataProviderTest::class, 'testOne'); - - $this->assertCount(9, $dataSets); - - $aCount = 0; - $bCount = 0; - $cCount = 0; - - for ($i = 0; $i < 9; $i++) { - $aCount += $dataSets[$i][0] != null ? 1 : 0; - $bCount += $dataSets[$i][1] != null ? 1 : 0; - $cCount += $dataSets[$i][2] != null ? 1 : 0; - } - - $this->assertEquals(3, $aCount); - $this->assertEquals(3, $bCount); - $this->assertEquals(3, $cCount); + $this->checkMultipleProviders('testOne'); } public function testMultipleYieldIteratorDataProviders(): void { - $dataSets = (new DataProvider)->providedData(MultipleDataProviderTest::class, 'testTwo'); - - $this->assertCount(9, $dataSets); - - $aCount = 0; - $bCount = 0; - $cCount = 0; - - for ($i = 0; $i < 9; $i++) { - $aCount += $dataSets[$i][0] != null ? 1 : 0; - $bCount += $dataSets[$i][1] != null ? 1 : 0; - $cCount += $dataSets[$i][2] != null ? 1 : 0; - } - - $this->assertEquals(3, $aCount); - $this->assertEquals(3, $bCount); - $this->assertEquals(3, $cCount); + $this->checkMultipleProviders('testTwo'); } public function testWithVariousIterableDataProvidersFromParent(): void @@ -75,16 +43,9 @@ public function testWithVariousIterableDataProvidersFromParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testFromParent'); $this->assertEquals([ - ['J'], - ['K'], - ['L'], - ['M'], - ['N'], - ['O'], - ['P'], - ['Q'], - ['R'], - + 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], ], $dataSets); } @@ -93,16 +54,9 @@ public function testWithVariousIterableDataProvidersInParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testInParent'); $this->assertEquals([ - ['J'], - ['K'], - ['L'], - ['M'], - ['N'], - ['O'], - ['P'], - ['Q'], - ['R'], - + 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], ], $dataSets); } @@ -111,16 +65,9 @@ public function testWithVariousIterableAbstractDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testAbstract'); $this->assertEquals([ - ['S'], - ['T'], - ['U'], - ['V'], - ['W'], - ['X'], - ['Y'], - ['Z'], - ['P'], - + 'asArrayProvider' => [['S'], ['T'], ['U'],], + 'asIteratorProvider' => [['V'], ['W'], ['X'],], + 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], ], $dataSets); } @@ -129,15 +76,9 @@ public function testWithVariousIterableStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testStatic'); $this->assertEquals([ - ['A'], - ['B'], - ['C'], - ['D'], - ['E'], - ['F'], - ['G'], - ['H'], - ['I'], + 'asArrayStaticProvider' => [['A'], ['B'], ['C'],], + 'asIteratorStaticProvider' => [['D'], ['E'], ['F'],], + 'asTraversableStaticProvider' => [['G'], ['H'], ['I'],], ], $dataSets); } @@ -146,15 +87,9 @@ public function testWithVariousIterableNonStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testNonStatic'); $this->assertEquals([ - ['S'], - ['T'], - ['U'], - ['V'], - ['W'], - ['X'], - ['Y'], - ['Z'], - ['P'], + 'asArrayProvider' => [['S'], ['T'], ['U'],], + 'asIteratorProvider' => [['V'], ['W'], ['X'],], + 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], ], $dataSets); } @@ -171,12 +106,12 @@ public function testTestWithAttribute(): void { $dataSets = (new DataProvider)->providedData(TestWithAttributeDataProviderTest::class, 'testWithAttribute'); - $this->assertSame([ + $this->assertSame(['testWith' => [ 'foo' => ['a', 'b'], 'bar' => ['c', 'd'], 0 => ['e', 'f'], 1 => ['g', 'h'], - ], $dataSets); + ]], $dataSets); } public function testTestWithAttributeWithDuplicateKey(): void @@ -196,4 +131,27 @@ public function testWithDuplicateKeyDataProviders(): void /* @noinspection UnusedFunctionResultInspection */ (new DataProvider)->providedData(DuplicateKeyDataProvidersTest::class, 'test'); } + + public function checkMultipleProviders(string $testMethodName): void + { + $dataSetsByProvider = (new DataProvider)->providedData(MultipleDataProviderTest::class, $testMethodName); + $this->assertCount(3, $dataSetsByProvider); + + $counts = ['a' => 0, 'b' => 0, 'c' => 0]; + $pos = ['a' => 0, 'b' => 1, 'c' => 2]; + + foreach ($dataSetsByProvider as $dataSet) { + for ($i = 0; $i < 3; $i++) { + foreach ($pos as $which => $where) { + if ($dataSet[$i][$where] !== null){ + $counts[$which]++; + } + } + } + } + + $this->assertEquals(3, $counts['a']); + $this->assertEquals(3, $counts['b']); + $this->assertEquals(3, $counts['c']); + } } From a1913f73084e433049cd656dfcc5db62418d4531 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sat, 12 Oct 2024 23:06:10 +0200 Subject: [PATCH 02/11] Adjust ExceptionTest.php to new field --- src/Metadata/Api/DataProvider.php | 4 ++-- tests/unit/Framework/Exception/ExceptionTest.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 61a4b1e9c96..273991017f4 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -163,7 +163,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod sprintf( 'The key "%s" has already been defined by a previous data provider', $key, - ), + ), method: $providerMethodName ); } $caseNames[$key] = 1; @@ -173,7 +173,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod sprintf( 'The key must be an integer or a string, %s given', get_debug_type($key), - ), + ), method: $providerMethodName ); } } diff --git a/tests/unit/Framework/Exception/ExceptionTest.php b/tests/unit/Framework/Exception/ExceptionTest.php index b8640210817..915ea397507 100644 --- a/tests/unit/Framework/Exception/ExceptionTest.php +++ b/tests/unit/Framework/Exception/ExceptionTest.php @@ -20,11 +20,12 @@ public function testExceptionSleep(): void { $actual = (new Exception)->__sleep(); - $this->assertCount(5, $actual); + $this->assertCount(6, $actual); $this->assertContains('serializableTrace', $actual); $this->assertContains('message', $actual); $this->assertContains('code', $actual); $this->assertContains('file', $actual); $this->assertContains('line', $actual); + $this->assertContains('method', $actual); } } From 965a0daa504d7e079d7e346dc33db6365388fa39 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sun, 13 Oct 2024 08:35:25 +0200 Subject: [PATCH 03/11] run php-cs-fixer --- src/Framework/Exception/Exception.php | 3 +- src/Framework/TestBuilder.php | 5 ++- src/Framework/TestCase.php | 16 +++----- src/Metadata/Api/DataProvider.php | 37 +++++++++---------- ...bstractVariousIterableDataProviderTest.php | 3 +- tests/unit/Metadata/Api/DataProviderTest.php | 34 ++++++++--------- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/Framework/Exception/Exception.php b/src/Framework/Exception/Exception.php index 7bf7600257b..971a4d02e74 100644 --- a/src/Framework/Exception/Exception.php +++ b/src/Framework/Exception/Exception.php @@ -42,11 +42,12 @@ */ class Exception extends RuntimeException implements \PHPUnit\Exception { + public ?string $method; + /** * @var list */ protected array $serializableTrace; - public ?string $method; public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null, ?string $method = null) { diff --git a/src/Framework/TestBuilder.php b/src/Framework/TestBuilder.php index 5f20d39e5d4..158adb4a68d 100644 --- a/src/Framework/TestBuilder.php +++ b/src/Framework/TestBuilder.php @@ -11,6 +11,7 @@ use function array_merge; use function assert; +use function reset; use PHPUnit\Metadata\Api\DataProvider; use PHPUnit\Metadata\Api\Groups; use PHPUnit\Metadata\Api\Requirements; @@ -91,8 +92,8 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam (new Groups)->groups($className, $methodName), ); - foreach ($data as $providerName => $providedData){ - foreach ($providedData as $_dataName => $_data){ + foreach ($data as $providerName => $providedData) { + foreach ($providedData as $_dataName => $_data) { $_test = new $className($methodName); $_test->setData($_dataName, $_data); diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 23da682955c..f6010347ce0 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -98,6 +98,10 @@ */ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test { + /** + * @var non-empty-string + */ + protected string $providerName; private ?bool $backupGlobals = null; /** @@ -146,11 +150,6 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T */ private string $methodName; - /** - * @var non-empty-string - */ - protected string $providerName; - /** * @var list */ @@ -365,21 +364,18 @@ final public function setGroups(array $groups): void $this->groups = $groups; } - /** - * @return string - */ public function getProviderName(): string { return $this->providerName; } /** - * @param string $providerName * @return $this */ - public function setProviderName(string $providerName): TestCase + public function setProviderName(string $providerName): self { $this->providerName = $providerName; + return $this; } diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 273991017f4..7f6815c048e 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -17,6 +17,7 @@ use function get_debug_type; use function is_array; use function is_int; +use function is_iterable; use function is_string; use function json_decode; use function json_last_error; @@ -94,8 +95,8 @@ public function providedData(string $className, string $methodName): ?array } /** - * @param class-string $testClassName Name of class with test - * @param non-empty-string $testMethodName Name of method containing test + * @param class-string $testClassName Name of class with test + * @param non-empty-string $testMethodName Name of method containing test * * @throws InvalidDataProviderException * @@ -111,7 +112,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod foreach ($dataProvider as $_dataProvider) { assert($_dataProvider instanceof DataProviderMetadata); - $providerClassName = $_dataProvider->className(); + $providerClassName = $_dataProvider->className(); $providerMethodName = $_dataProvider->methodName(); $dataProviderMethod = new ClassMethod($providerClassName, $providerMethodName); @@ -139,41 +140,47 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod } $data = $providerClassName::$providerMethodName(); + if (!is_iterable($data)) { $this->throwInvalid('does not provide iterable type', $_dataProvider); } } catch (Throwable $e) { $this->finishMethods($testMethod, $methodsCalled); + throw new InvalidDataProviderException( $e->getMessage(), $e->getCode(), $e, - $providerMethodName + $providerMethodName, ); } $result = []; + foreach ($data as $key => $value) { if (is_int($key)) { $result[] = $value; } elseif (is_string($key)) { if (isset($caseNames[$key])) { $this->finishMethods($testMethod, $methodsCalled); + throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous data provider', $key, - ), method: $providerMethodName + ), + method: $providerMethodName, ); } $caseNames[$key] = 1; - $result[$key] = $value; + $result[$key] = $value; } else { throw new InvalidDataProviderException( sprintf( 'The key must be an integer or a string, %s given', get_debug_type($key), - ), method: $providerMethodName + ), + method: $providerMethodName, ); } } @@ -184,12 +191,8 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod return $return; } - /** - * @param string $message - * @param DataProviderMetadata $dataProvider - * @return never - */ - private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never { + private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never + { throw new InvalidDataProviderException( sprintf( 'Data Provider method %s::%s() ', @@ -199,12 +202,8 @@ private function throwInvalid(string $message, DataProviderMetadata $dataProvide ); } - /** - * @param ClassMethod $method - * @param array $methodsCalled - * @return void - */ - private function finishMethods(ClassMethod $method, array $methodsCalled): void { + private function finishMethods(ClassMethod $method, array $methodsCalled): void + { Event\Facade::emitter()->dataProviderMethodFinished( $method, ...$methodsCalled, diff --git a/tests/_files/AbstractVariousIterableDataProviderTest.php b/tests/_files/AbstractVariousIterableDataProviderTest.php index 95ba6d8f214..d33270f6977 100644 --- a/tests/_files/AbstractVariousIterableDataProviderTest.php +++ b/tests/_files/AbstractVariousIterableDataProviderTest.php @@ -9,6 +9,7 @@ */ namespace PHPUnit\TestFixture; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; abstract class AbstractVariousIterableDataProviderTest @@ -22,7 +23,7 @@ public static function asArrayProviderInParent(): array ]; } - public static function asIteratorProviderInParent(): \Generator + public static function asIteratorProviderInParent(): Generator { yield ['M']; diff --git a/tests/unit/Metadata/Api/DataProviderTest.php b/tests/unit/Metadata/Api/DataProviderTest.php index ea4ac6eef86..104a928d098 100644 --- a/tests/unit/Metadata/Api/DataProviderTest.php +++ b/tests/unit/Metadata/Api/DataProviderTest.php @@ -43,9 +43,9 @@ public function testWithVariousIterableDataProvidersFromParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testFromParent'); $this->assertEquals([ - 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], - 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], - 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], + 'asArrayProviderInParent' => [['J'], ['K'], ['L']], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O']], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R']], ], $dataSets); } @@ -54,9 +54,9 @@ public function testWithVariousIterableDataProvidersInParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testInParent'); $this->assertEquals([ - 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], - 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], - 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], + 'asArrayProviderInParent' => [['J'], ['K'], ['L']], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O']], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R']], ], $dataSets); } @@ -65,9 +65,9 @@ public function testWithVariousIterableAbstractDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testAbstract'); $this->assertEquals([ - 'asArrayProvider' => [['S'], ['T'], ['U'],], - 'asIteratorProvider' => [['V'], ['W'], ['X'],], - 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], + 'asArrayProvider' => [['S'], ['T'], ['U']], + 'asIteratorProvider' => [['V'], ['W'], ['X']], + 'asTraversableProvider' => [['Y'], ['Z'], ['P']], ], $dataSets); } @@ -76,9 +76,9 @@ public function testWithVariousIterableStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testStatic'); $this->assertEquals([ - 'asArrayStaticProvider' => [['A'], ['B'], ['C'],], - 'asIteratorStaticProvider' => [['D'], ['E'], ['F'],], - 'asTraversableStaticProvider' => [['G'], ['H'], ['I'],], + 'asArrayStaticProvider' => [['A'], ['B'], ['C']], + 'asIteratorStaticProvider' => [['D'], ['E'], ['F']], + 'asTraversableStaticProvider' => [['G'], ['H'], ['I']], ], $dataSets); } @@ -87,9 +87,9 @@ public function testWithVariousIterableNonStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testNonStatic'); $this->assertEquals([ - 'asArrayProvider' => [['S'], ['T'], ['U'],], - 'asIteratorProvider' => [['V'], ['W'], ['X'],], - 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], + 'asArrayProvider' => [['S'], ['T'], ['U']], + 'asIteratorProvider' => [['V'], ['W'], ['X']], + 'asTraversableProvider' => [['Y'], ['Z'], ['P']], ], $dataSets); } @@ -138,12 +138,12 @@ public function checkMultipleProviders(string $testMethodName): void $this->assertCount(3, $dataSetsByProvider); $counts = ['a' => 0, 'b' => 0, 'c' => 0]; - $pos = ['a' => 0, 'b' => 1, 'c' => 2]; + $pos = ['a' => 0, 'b' => 1, 'c' => 2]; foreach ($dataSetsByProvider as $dataSet) { for ($i = 0; $i < 3; $i++) { foreach ($pos as $which => $where) { - if ($dataSet[$i][$where] !== null){ + if ($dataSet[$i][$where] !== null) { $counts[$which]++; } } From f57a194fbd84fe35fbf4636946adb143aebee19a Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sun, 13 Oct 2024 19:36:38 +0200 Subject: [PATCH 04/11] make phpstan happy --- src/Metadata/Api/DataProvider.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 7f6815c048e..9e8f9a28415 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -202,6 +202,9 @@ private function throwInvalid(string $message, DataProviderMetadata $dataProvide ); } + /** + * @param ClassMethod[] $methodsCalled + */ private function finishMethods(ClassMethod $method, array $methodsCalled): void { Event\Facade::emitter()->dataProviderMethodFinished( From 79e2a5bf38280bdcd650be73868de5463163c4e9 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Mon, 14 Oct 2024 18:57:12 +0200 Subject: [PATCH 05/11] adjust e2e --- src/Metadata/Api/DataProvider.php | 10 ++++++++-- .../end-to-end/event/data-provider-duplicate-key.phpt | 2 +- tests/end-to-end/event/data-provider-empty.phpt | 2 +- tests/end-to-end/event/data-provider-exception.phpt | 2 +- .../event/data-provider-expects-argument.phpt | 2 +- tests/end-to-end/event/data-provider-not-public.phpt | 2 +- tests/end-to-end/event/data-provider-not-static.phpt | 2 +- .../event/invalid-data-provider-with-passing-test.phpt | 2 +- tests/end-to-end/event/invalid-data-provider.phpt | 2 +- tests/end-to-end/event/testwith-annotation.phpt | 4 ++-- tests/end-to-end/regression/2137-filter.phpt | 4 ++-- tests/end-to-end/regression/2137-no_filter.phpt | 4 ++-- tests/end-to-end/regression/4625.phpt | 2 +- tests/end-to-end/regression/498.phpt | 2 +- tests/end-to-end/regression/5138.phpt | 2 +- tests/end-to-end/regression/5451.phpt | 2 +- tests/end-to-end/regression/5908-list-tests-xml.phpt | 2 +- tests/end-to-end/regression/5908-list-tests.phpt | 2 +- tests/end-to-end/regression/765.phpt | 2 +- 19 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 9e8f9a28415..aad8300bf2f 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -22,8 +22,10 @@ use function json_decode; use function json_last_error; use function json_last_error_msg; +use function key; use function preg_match; use function preg_replace; +use function reset; use function rtrim; use function sprintf; use function str_replace; @@ -71,13 +73,14 @@ public function providedData(string $className, string $methodName): ?array $data = ['testWith' => $this->dataProvidedByMetadata($testWith)]; } - if ($data === [] || $data === ['testWith' => []]) { + if ($data === [] || reset($data) === []) { throw new InvalidDataProviderException( 'Empty data set provided by data provider', + method: key($data), ); } - foreach ($data as $providedData) { + foreach ($data as $providerMethodName => $providedData) { foreach ($providedData as $key => $value) { if (!is_array($value)) { throw new InvalidDataProviderException( @@ -86,6 +89,7 @@ public function providedData(string $className, string $methodName): ?array is_int($key) ? '#' . $key : '"' . $key . '"', get_debug_type($value), ), + method: $providerMethodName, ); } } @@ -284,6 +288,7 @@ private function dataProvidedByTestWithAnnotation(string $className, string $met if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidDataProviderException( 'The data set for the @testWith annotation cannot be parsed: ' . json_last_error_msg(), + method: 'JSON', ); } @@ -293,6 +298,7 @@ private function dataProvidedByTestWithAnnotation(string $className, string $met if (!$data) { throw new InvalidDataProviderException( 'The data set for the @testWith annotation cannot be parsed.', + method: 'testWithAnnotation', ); } diff --git a/tests/end-to-end/event/data-provider-duplicate-key.phpt b/tests/end-to-end/event/data-provider-duplicate-key.phpt index 62d005c6f17..18b174e0bca 100644 --- a/tests/end-to-end/event/data-provider-duplicate-key.phpt +++ b/tests/end-to-end/event/data-provider-duplicate-key.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\DataProviderDuplicateKeyT Data Provider Method Finished for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething: - PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething) -The data provider specified for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething is invalid The key "key" has already been defined by a previous data provider Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-empty.phpt b/tests/end-to-end/event/data-provider-empty.phpt index 496e310bca7..7187956c10c 100644 --- a/tests/end-to-end/event/data-provider-empty.phpt +++ b/tests/end-to-end/event/data-provider-empty.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\EmptyDataProviderTest::pr Data Provider Method Finished for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase: - PHPUnit\TestFixture\Event\EmptyDataProviderTest::providerMethod Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase) -The data provider specified for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase is invalid +The data provider providerMethod specified for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase is invalid Empty data set provided by data provider Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\EmptyDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-exception.phpt b/tests/end-to-end/event/data-provider-exception.phpt index c85357566c4..5efd93eaf87 100644 --- a/tests/end-to-end/event/data-provider-exception.phpt +++ b/tests/end-to-end/event/data-provider-exception.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\ExceptionInDataProviderTe Data Provider Method Finished for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne: - PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne is invalid message Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\ExceptionInDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-expects-argument.phpt b/tests/end-to-end/event/data-provider-expects-argument.phpt index cf8af7ec6ba..152b1e163c7 100644 --- a/tests/end-to-end/event/data-provider-expects-argument.phpt +++ b/tests/end-to-end/event/data-provider-expects-argument.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\ArgumentDataProviderTest: Data Provider Method Finished for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\ArgumentDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\ArgumentDataProviderTest::values() expects an argument Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\ArgumentDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-not-public.phpt b/tests/end-to-end/event/data-provider-not-public.phpt index 5c1aedc95a6..19975ef2cbb 100644 --- a/tests/end-to-end/event/data-provider-not-public.phpt +++ b/tests/end-to-end/event/data-provider-not-public.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\PrivateDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\PrivateDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\PrivateDataProviderTest::values() is not public Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\PrivateDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-not-static.phpt b/tests/end-to-end/event/data-provider-not-static.phpt index 8ee9869c173..c1615bd3933 100644 --- a/tests/end-to-end/event/data-provider-not-static.phpt +++ b/tests/end-to-end/event/data-provider-not-static.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\DynamicDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\DynamicDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\DynamicDataProviderTest::values() is not static Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\DynamicDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt b/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt index 4e6b19e3cae..d94e861a183 100644 --- a/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt +++ b/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\InvalidDataProviderWithOn Data Provider Method Finished for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne: - PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne is invalid Data set #0 is invalid, expected array but got int Test Suite Loaded (1 test) Test Runner Started diff --git a/tests/end-to-end/event/invalid-data-provider.phpt b/tests/end-to-end/event/invalid-data-provider.phpt index 761b7236eed..85a568ca9d0 100644 --- a/tests/end-to-end/event/invalid-data-provider.phpt +++ b/tests/end-to-end/event/invalid-data-provider.phpt @@ -26,7 +26,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\InvalidDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne: - PHPUnit\TestFixture\Event\InvalidDataProviderTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne is invalid Data set #0 is invalid, expected array but got int Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\InvalidDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/testwith-annotation.phpt b/tests/end-to-end/event/testwith-annotation.phpt index 55b02a6c9f2..2f54b421ad3 100644 --- a/tests/end-to-end/event/testwith-annotation.phpt +++ b/tests/end-to-end/event/testwith-annotation.phpt @@ -23,10 +23,10 @@ PHPUnit Started (PHPUnit %s using %s) Test Runner Configured Event Facade Sealed Test Triggered PHPUnit Error (PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetIsInvalidJson) -The data provider specified for PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetIsInvalidJson is invalid +The data provider JSON specified for PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetIsInvalidJson is invalid The data set for the @testWith annotation cannot be parsed: State mismatch (invalid or malformed JSON) Test Triggered PHPUnit Error (PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetCannotBeParsed) -The data provider specified for PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetCannotBeParsed is invalid +The data provider testWithAnnotation specified for PHPUnit\TestFixture\Metadata\Annotation\TestWithTest::testDataSetCannotBeParsed is invalid The data set for the @testWith annotation cannot be parsed. Test Suite Loaded (1 test) Test Runner Started diff --git a/tests/end-to-end/regression/2137-filter.phpt b/tests/end-to-end/regression/2137-filter.phpt index 7b56bcda1c4..df3f3fb7eb8 100644 --- a/tests/end-to-end/regression/2137-filter.phpt +++ b/tests/end-to-end/regression/2137-filter.phpt @@ -18,13 +18,13 @@ Runtime: %s There were 2 PHPUnit errors: 1) PHPUnit\TestFixture\Issue2137Test::testBrandService -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid Data set #0 is invalid, expected array but got stdClass %s:%d 2) PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid Data set #0 is invalid, expected array but got stdClass %s:%d diff --git a/tests/end-to-end/regression/2137-no_filter.phpt b/tests/end-to-end/regression/2137-no_filter.phpt index 2f68ffbbfaf..574ad18c4fc 100644 --- a/tests/end-to-end/regression/2137-no_filter.phpt +++ b/tests/end-to-end/regression/2137-no_filter.phpt @@ -16,13 +16,13 @@ Runtime: %s There were 2 PHPUnit errors: 1) PHPUnit\TestFixture\Issue2137Test::testBrandService -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid Data set #0 is invalid, expected array but got stdClass %s:%d 2) PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid Data set #0 is invalid, expected array but got stdClass %s:%d diff --git a/tests/end-to-end/regression/4625.phpt b/tests/end-to-end/regression/4625.phpt index 7b0cb1039eb..cddf36c0e1e 100644 --- a/tests/end-to-end/regression/4625.phpt +++ b/tests/end-to-end/regression/4625.phpt @@ -21,7 +21,7 @@ Time: %s, Memory: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue4625\Issue4625Test::testOne -The data provider specified for PHPUnit\TestFixture\Issue4625\Issue4625Test::testOne is invalid +The data provider dataProvider specified for PHPUnit\TestFixture\Issue4625\Issue4625Test::testOne is invalid The key must be an integer or a string, array given %s:%d diff --git a/tests/end-to-end/regression/498.phpt b/tests/end-to-end/regression/498.phpt index eb69c45f5d3..432752a92a6 100644 --- a/tests/end-to-end/regression/498.phpt +++ b/tests/end-to-end/regression/498.phpt @@ -18,7 +18,7 @@ Runtime: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue498Test::shouldBeFalse -The data provider specified for PHPUnit\TestFixture\Issue498Test::shouldBeFalse is invalid +The data provider shouldBeFalseDataProvider specified for PHPUnit\TestFixture\Issue498Test::shouldBeFalse is invalid Can't create the data %s:%d diff --git a/tests/end-to-end/regression/5138.phpt b/tests/end-to-end/regression/5138.phpt index 5675237ee26..6038cb68e18 100644 --- a/tests/end-to-end/regression/5138.phpt +++ b/tests/end-to-end/regression/5138.phpt @@ -17,7 +17,7 @@ Configuration: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue5138Test::testOne -The data provider specified for PHPUnit\TestFixture\Issue5138Test::testOne is invalid +The data provider provideData specified for PHPUnit\TestFixture\Issue5138Test::testOne is invalid message %s:%d diff --git a/tests/end-to-end/regression/5451.phpt b/tests/end-to-end/regression/5451.phpt index 942cf44bf21..a19798eea6f 100644 --- a/tests/end-to-end/regression/5451.phpt +++ b/tests/end-to-end/regression/5451.phpt @@ -25,7 +25,7 @@ Time: %s, Memory: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider -The data provider specified for PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider is invalid +The data provider dataProviderThatTriggersPhpError specified for PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider is invalid Call to a member function bar() on array %s%eIssue5451Test.php:26 diff --git a/tests/end-to-end/regression/5908-list-tests-xml.phpt b/tests/end-to-end/regression/5908-list-tests-xml.phpt index d4034071955..e12efe28bf0 100644 --- a/tests/end-to-end/regression/5908-list-tests-xml.phpt +++ b/tests/end-to-end/regression/5908-list-tests-xml.phpt @@ -20,5 +20,5 @@ PHPUnit %s by Sebastian Bergmann and contributors. There were errors: -The data provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid message diff --git a/tests/end-to-end/regression/5908-list-tests.phpt b/tests/end-to-end/regression/5908-list-tests.phpt index 88757a15215..6b759e7b2d3 100644 --- a/tests/end-to-end/regression/5908-list-tests.phpt +++ b/tests/end-to-end/regression/5908-list-tests.phpt @@ -15,5 +15,5 @@ PHPUnit %s by Sebastian Bergmann and contributors. There were errors: -The data provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid message diff --git a/tests/end-to-end/regression/765.phpt b/tests/end-to-end/regression/765.phpt index 0aac3d9e8d1..e4e958fc9fe 100644 --- a/tests/end-to-end/regression/765.phpt +++ b/tests/end-to-end/regression/765.phpt @@ -25,7 +25,7 @@ Time: %s, Memory: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue765Test::testDependent -The data provider specified for PHPUnit\TestFixture\Issue765Test::testDependent is invalid +The data provider dependentProvider specified for PHPUnit\TestFixture\Issue765Test::testDependent is invalid %s:%d From 5bb72a3c3e2ba65befead62c9a2f2d3179d5d82e Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Mon, 7 Oct 2024 16:25:59 +0200 Subject: [PATCH 06/11] Save names of data providers for better debug message and possibility of more generic tests --- src/Framework/Exception/Exception.php | 4 +- src/Framework/TestBuilder.php | 27 ++-- src/Framework/TestCase.php | 23 ++++ src/Framework/TestSuite.php | 3 +- src/Metadata/Api/DataProvider.php | 123 +++++++++-------- ...bstractVariousIterableDataProviderTest.php | 6 +- tests/unit/Metadata/Api/DataProviderTest.php | 126 ++++++------------ 7 files changed, 153 insertions(+), 159 deletions(-) diff --git a/src/Framework/Exception/Exception.php b/src/Framework/Exception/Exception.php index e35b0d50520..7bf7600257b 100644 --- a/src/Framework/Exception/Exception.php +++ b/src/Framework/Exception/Exception.php @@ -46,8 +46,9 @@ class Exception extends RuntimeException implements \PHPUnit\Exception * @var list */ protected array $serializableTrace; + public ?string $method; - public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null) + public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null, ?string $method = null) { /** * @see https://github.com/sebastianbergmann/phpunit/issues/5965 @@ -68,6 +69,7 @@ public function __construct(string $message = '', int|string $code = 0, ?Throwab foreach (array_keys($this->serializableTrace) as $key) { unset($this->serializableTrace[$key]['args']); } + $this->method = $method; } public function __sleep(): array diff --git a/src/Framework/TestBuilder.php b/src/Framework/TestBuilder.php index 5c3effc7a35..5f20d39e5d4 100644 --- a/src/Framework/TestBuilder.php +++ b/src/Framework/TestBuilder.php @@ -47,7 +47,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou $data = (new DataProvider)->providedData($className, $methodName); } - if ($data !== null) { + if ($data !== null && reset($data) !== null) { return $this->buildDataProviderTestSuite( $methodName, $className, @@ -91,20 +91,23 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam (new Groups)->groups($className, $methodName), ); - foreach ($data as $_dataName => $_data) { - $_test = new $className($methodName); + foreach ($data as $providerName => $providedData){ + foreach ($providedData as $_dataName => $_data){ + $_test = new $className($methodName); - $_test->setData($_dataName, $_data); + $_test->setData($_dataName, $_data); - $this->configureTestCase( - $_test, - $runTestInSeparateProcess, - $preserveGlobalState, - $runClassInSeparateProcess, - $backupSettings, - ); + $this->configureTestCase( + $_test, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings, + ); - $dataProviderTestSuite->addTest($_test, $groups); + $_test->setProviderName($providerName); + $dataProviderTestSuite->addTest($_test, $groups); + } } return $dataProviderTestSuite; diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 2d749ea2433..23da682955c 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -146,6 +146,11 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T */ private string $methodName; + /** + * @var non-empty-string + */ + protected string $providerName; + /** * @var list */ @@ -360,6 +365,24 @@ final public function setGroups(array $groups): void $this->groups = $groups; } + /** + * @return string + */ + public function getProviderName(): string + { + return $this->providerName; + } + + /** + * @param string $providerName + * @return $this + */ + public function setProviderName(string $providerName): TestCase + { + $this->providerName = $providerName; + return $this; + } + /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ diff --git a/src/Framework/TestSuite.php b/src/Framework/TestSuite.php index 7f45914372e..9d08a22a26a 100644 --- a/src/Framework/TestSuite.php +++ b/src/Framework/TestSuite.php @@ -521,7 +521,8 @@ protected function addTestMethod(ReflectionClass $class, ReflectionMethod $metho Event\TestData\TestDataCollection::fromArray([]), ), sprintf( - "The data provider specified for %s::%s is invalid\n%s", + "The data provider %s specified for %s::%s is invalid\n%s", + $e->method, $className, $methodName, $this->throwableToString($e), diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index a738bca08be..b2c2433e681 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -17,6 +17,7 @@ use function is_string; use function sprintf; use PHPUnit\Event; +use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Framework\InvalidDataProviderException; use PHPUnit\Metadata\DataProvider as DataProviderMetadata; use PHPUnit\Metadata\MetadataCollection; @@ -52,24 +53,26 @@ public function providedData(string $className, string $methodName): ?array if ($dataProvider->isNotEmpty()) { $data = $this->dataProvidedByMethods($className, $methodName, $dataProvider); } else { - $data = $this->dataProvidedByMetadata($testWith); + $data = ['testWith' => $this->dataProvidedByMetadata($testWith)]; } - if ($data === []) { + if ($data === [] || $data === ['testWith' => []]) { throw new InvalidDataProviderException( 'Empty data set provided by data provider', ); } - foreach ($data as $key => $value) { - if (!is_array($value)) { - throw new InvalidDataProviderException( - sprintf( - 'Data set %s is invalid, expected array but got %s', - is_int($key) ? '#' . $key : '"' . $key . '"', - get_debug_type($value), - ), - ); + foreach ($data as $providedData) { + foreach ($providedData as $key => $value) { + if (!is_array($value)) { + throw new InvalidDataProviderException( + sprintf( + 'Data set %s is invalid, expected array but got %s', + is_int($key) ? '#' . $key : '"' . $key . '"', + get_debug_type($value), + ), + ); + } } } @@ -77,23 +80,26 @@ public function providedData(string $className, string $methodName): ?array } /** - * @param class-string $className - * @param non-empty-string $methodName + * @param class-string $testClassName Name of class with test + * @param non-empty-string $testMethodName Name of method containing test * * @throws InvalidDataProviderException * * @return array> */ - private function dataProvidedByMethods(string $className, string $methodName, MetadataCollection $dataProvider): array + private function dataProvidedByMethods(string $testClassName, string $testMethodName, MetadataCollection $dataProvider): array { - $testMethod = new Event\Code\ClassMethod($className, $methodName); + $testMethod = new ClassMethod($testClassName, $testMethodName); $methodsCalled = []; - $result = []; + $return = []; + $caseNames = []; foreach ($dataProvider as $_dataProvider) { assert($_dataProvider instanceof DataProviderMetadata); - $dataProviderMethod = new Event\Code\ClassMethod($_dataProvider->className(), $_dataProvider->methodName()); + $providerClassName = $_dataProvider->className(); + $providerMethodName = $_dataProvider->methodName(); + $dataProviderMethod = new ClassMethod($providerClassName, $providerMethodName); Event\Facade::emitter()->dataProviderMethodCalled( $testMethod, @@ -103,65 +109,42 @@ private function dataProvidedByMethods(string $className, string $methodName, Me $methodsCalled[] = $dataProviderMethod; try { - $class = new ReflectionClass($_dataProvider->className()); - $method = $class->getMethod($_dataProvider->methodName()); + $class = new ReflectionClass($providerClassName); + $method = $class->getMethod($providerMethodName); if (!$method->isPublic()) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() is not public', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('is not public', $_dataProvider); } if (!$method->isStatic()) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() is not static', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('is not static', $_dataProvider); } if ($method->getNumberOfParameters() > 0) { - throw new InvalidDataProviderException( - sprintf( - 'Data Provider method %s::%s() expects an argument', - $_dataProvider->className(), - $_dataProvider->methodName(), - ), - ); + $this->throwInvalid('expects an argument', $_dataProvider); } - $className = $_dataProvider->className(); - $methodName = $_dataProvider->methodName(); - $data = $className::$methodName(); + $data = $providerClassName::$providerMethodName(); + if (!is_iterable($data)) { + $this->throwInvalid('does not provide iterable type', $_dataProvider); + } } catch (Throwable $e) { - Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, - ...$methodsCalled, - ); - + $this->finishMethods($testMethod, $methodsCalled); throw new InvalidDataProviderException( $e->getMessage(), $e->getCode(), $e, + $providerMethodName ); } + $result = []; foreach ($data as $key => $value) { if (is_int($key)) { $result[] = $value; } elseif (is_string($key)) { - if (array_key_exists($key, $result)) { - Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, - ...$methodsCalled, - ); - + if (isset($caseNames[$key])) { + $this->finishMethods($testMethod, $methodsCalled); throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous data provider', @@ -169,7 +152,7 @@ private function dataProvidedByMethods(string $className, string $methodName, Me ), ); } - + $caseNames[$key] = 1; $result[$key] = $value; } else { throw new InvalidDataProviderException( @@ -180,14 +163,38 @@ private function dataProvidedByMethods(string $className, string $methodName, Me ); } } + $return[$providerMethodName] = $result; } + $this->finishMethods($testMethod, $methodsCalled); + + return $return; + } + /** + * @param string $message + * @param DataProviderMetadata $dataProvider + * @return never + */ + private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never { + throw new InvalidDataProviderException( + sprintf( + 'Data Provider method %s::%s() ', + $dataProvider->className(), + $dataProvider->methodName(), + ) . $message, + ); + } + + /** + * @param ClassMethod $method + * @param array $methodsCalled + * @return void + */ + private function finishMethods(ClassMethod $method, array $methodsCalled): void { Event\Facade::emitter()->dataProviderMethodFinished( - $testMethod, + $method, ...$methodsCalled, ); - - return $result; } /** diff --git a/tests/_files/AbstractVariousIterableDataProviderTest.php b/tests/_files/AbstractVariousIterableDataProviderTest.php index d2d390e8d43..95ba6d8f214 100644 --- a/tests/_files/AbstractVariousIterableDataProviderTest.php +++ b/tests/_files/AbstractVariousIterableDataProviderTest.php @@ -13,7 +13,7 @@ abstract class AbstractVariousIterableDataProviderTest { - public static function asArrayProviderInParent() + public static function asArrayProviderInParent(): array { return [ ['J'], @@ -22,7 +22,7 @@ public static function asArrayProviderInParent() ]; } - public static function asIteratorProviderInParent() + public static function asIteratorProviderInParent(): \Generator { yield ['M']; @@ -31,7 +31,7 @@ public static function asIteratorProviderInParent() yield ['O']; } - public static function asTraversableProviderInParent() + public static function asTraversableProviderInParent(): WrapperIteratorAggregate { return new WrapperIteratorAggregate([ ['P'], diff --git a/tests/unit/Metadata/Api/DataProviderTest.php b/tests/unit/Metadata/Api/DataProviderTest.php index 442b58cd8be..ea4ac6eef86 100644 --- a/tests/unit/Metadata/Api/DataProviderTest.php +++ b/tests/unit/Metadata/Api/DataProviderTest.php @@ -30,44 +30,12 @@ final class DataProviderTest extends TestCase */ public function testMultipleDataProviders(): void { - $dataSets = (new DataProvider)->providedData(MultipleDataProviderTest::class, 'testOne'); - - $this->assertCount(9, $dataSets); - - $aCount = 0; - $bCount = 0; - $cCount = 0; - - for ($i = 0; $i < 9; $i++) { - $aCount += $dataSets[$i][0] != null ? 1 : 0; - $bCount += $dataSets[$i][1] != null ? 1 : 0; - $cCount += $dataSets[$i][2] != null ? 1 : 0; - } - - $this->assertEquals(3, $aCount); - $this->assertEquals(3, $bCount); - $this->assertEquals(3, $cCount); + $this->checkMultipleProviders('testOne'); } public function testMultipleYieldIteratorDataProviders(): void { - $dataSets = (new DataProvider)->providedData(MultipleDataProviderTest::class, 'testTwo'); - - $this->assertCount(9, $dataSets); - - $aCount = 0; - $bCount = 0; - $cCount = 0; - - for ($i = 0; $i < 9; $i++) { - $aCount += $dataSets[$i][0] != null ? 1 : 0; - $bCount += $dataSets[$i][1] != null ? 1 : 0; - $cCount += $dataSets[$i][2] != null ? 1 : 0; - } - - $this->assertEquals(3, $aCount); - $this->assertEquals(3, $bCount); - $this->assertEquals(3, $cCount); + $this->checkMultipleProviders('testTwo'); } public function testWithVariousIterableDataProvidersFromParent(): void @@ -75,16 +43,9 @@ public function testWithVariousIterableDataProvidersFromParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testFromParent'); $this->assertEquals([ - ['J'], - ['K'], - ['L'], - ['M'], - ['N'], - ['O'], - ['P'], - ['Q'], - ['R'], - + 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], ], $dataSets); } @@ -93,16 +54,9 @@ public function testWithVariousIterableDataProvidersInParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testInParent'); $this->assertEquals([ - ['J'], - ['K'], - ['L'], - ['M'], - ['N'], - ['O'], - ['P'], - ['Q'], - ['R'], - + 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], ], $dataSets); } @@ -111,16 +65,9 @@ public function testWithVariousIterableAbstractDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testAbstract'); $this->assertEquals([ - ['S'], - ['T'], - ['U'], - ['V'], - ['W'], - ['X'], - ['Y'], - ['Z'], - ['P'], - + 'asArrayProvider' => [['S'], ['T'], ['U'],], + 'asIteratorProvider' => [['V'], ['W'], ['X'],], + 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], ], $dataSets); } @@ -129,15 +76,9 @@ public function testWithVariousIterableStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testStatic'); $this->assertEquals([ - ['A'], - ['B'], - ['C'], - ['D'], - ['E'], - ['F'], - ['G'], - ['H'], - ['I'], + 'asArrayStaticProvider' => [['A'], ['B'], ['C'],], + 'asIteratorStaticProvider' => [['D'], ['E'], ['F'],], + 'asTraversableStaticProvider' => [['G'], ['H'], ['I'],], ], $dataSets); } @@ -146,15 +87,9 @@ public function testWithVariousIterableNonStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testNonStatic'); $this->assertEquals([ - ['S'], - ['T'], - ['U'], - ['V'], - ['W'], - ['X'], - ['Y'], - ['Z'], - ['P'], + 'asArrayProvider' => [['S'], ['T'], ['U'],], + 'asIteratorProvider' => [['V'], ['W'], ['X'],], + 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], ], $dataSets); } @@ -171,12 +106,12 @@ public function testTestWithAttribute(): void { $dataSets = (new DataProvider)->providedData(TestWithAttributeDataProviderTest::class, 'testWithAttribute'); - $this->assertSame([ + $this->assertSame(['testWith' => [ 'foo' => ['a', 'b'], 'bar' => ['c', 'd'], 0 => ['e', 'f'], 1 => ['g', 'h'], - ], $dataSets); + ]], $dataSets); } public function testTestWithAttributeWithDuplicateKey(): void @@ -196,4 +131,27 @@ public function testWithDuplicateKeyDataProviders(): void /* @noinspection UnusedFunctionResultInspection */ (new DataProvider)->providedData(DuplicateKeyDataProvidersTest::class, 'test'); } + + public function checkMultipleProviders(string $testMethodName): void + { + $dataSetsByProvider = (new DataProvider)->providedData(MultipleDataProviderTest::class, $testMethodName); + $this->assertCount(3, $dataSetsByProvider); + + $counts = ['a' => 0, 'b' => 0, 'c' => 0]; + $pos = ['a' => 0, 'b' => 1, 'c' => 2]; + + foreach ($dataSetsByProvider as $dataSet) { + for ($i = 0; $i < 3; $i++) { + foreach ($pos as $which => $where) { + if ($dataSet[$i][$where] !== null){ + $counts[$which]++; + } + } + } + } + + $this->assertEquals(3, $counts['a']); + $this->assertEquals(3, $counts['b']); + $this->assertEquals(3, $counts['c']); + } } From f8431d5ae6ef7513cf17f0374715744b2e9e3174 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sat, 12 Oct 2024 23:06:10 +0200 Subject: [PATCH 07/11] Adjust ExceptionTest.php to new field --- src/Metadata/Api/DataProvider.php | 4 ++-- tests/unit/Framework/Exception/ExceptionTest.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index b2c2433e681..755ba1047c1 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -149,7 +149,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod sprintf( 'The key "%s" has already been defined by a previous data provider', $key, - ), + ), method: $providerMethodName ); } $caseNames[$key] = 1; @@ -159,7 +159,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod sprintf( 'The key must be an integer or a string, %s given', get_debug_type($key), - ), + ), method: $providerMethodName ); } } diff --git a/tests/unit/Framework/Exception/ExceptionTest.php b/tests/unit/Framework/Exception/ExceptionTest.php index b8640210817..915ea397507 100644 --- a/tests/unit/Framework/Exception/ExceptionTest.php +++ b/tests/unit/Framework/Exception/ExceptionTest.php @@ -20,11 +20,12 @@ public function testExceptionSleep(): void { $actual = (new Exception)->__sleep(); - $this->assertCount(5, $actual); + $this->assertCount(6, $actual); $this->assertContains('serializableTrace', $actual); $this->assertContains('message', $actual); $this->assertContains('code', $actual); $this->assertContains('file', $actual); $this->assertContains('line', $actual); + $this->assertContains('method', $actual); } } From e5ff61e4222fd5103a8756b61ad1c534d44617b1 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sun, 13 Oct 2024 08:35:25 +0200 Subject: [PATCH 08/11] run php-cs-fixer --- src/Framework/Exception/Exception.php | 3 +- src/Framework/TestBuilder.php | 5 ++- src/Framework/TestCase.php | 16 +++----- src/Metadata/Api/DataProvider.php | 37 +++++++++---------- ...bstractVariousIterableDataProviderTest.php | 3 +- tests/unit/Metadata/Api/DataProviderTest.php | 34 ++++++++--------- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/Framework/Exception/Exception.php b/src/Framework/Exception/Exception.php index 7bf7600257b..971a4d02e74 100644 --- a/src/Framework/Exception/Exception.php +++ b/src/Framework/Exception/Exception.php @@ -42,11 +42,12 @@ */ class Exception extends RuntimeException implements \PHPUnit\Exception { + public ?string $method; + /** * @var list */ protected array $serializableTrace; - public ?string $method; public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null, ?string $method = null) { diff --git a/src/Framework/TestBuilder.php b/src/Framework/TestBuilder.php index 5f20d39e5d4..158adb4a68d 100644 --- a/src/Framework/TestBuilder.php +++ b/src/Framework/TestBuilder.php @@ -11,6 +11,7 @@ use function array_merge; use function assert; +use function reset; use PHPUnit\Metadata\Api\DataProvider; use PHPUnit\Metadata\Api\Groups; use PHPUnit\Metadata\Api\Requirements; @@ -91,8 +92,8 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam (new Groups)->groups($className, $methodName), ); - foreach ($data as $providerName => $providedData){ - foreach ($providedData as $_dataName => $_data){ + foreach ($data as $providerName => $providedData) { + foreach ($providedData as $_dataName => $_data) { $_test = new $className($methodName); $_test->setData($_dataName, $_data); diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 23da682955c..f6010347ce0 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -98,6 +98,10 @@ */ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test { + /** + * @var non-empty-string + */ + protected string $providerName; private ?bool $backupGlobals = null; /** @@ -146,11 +150,6 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T */ private string $methodName; - /** - * @var non-empty-string - */ - protected string $providerName; - /** * @var list */ @@ -365,21 +364,18 @@ final public function setGroups(array $groups): void $this->groups = $groups; } - /** - * @return string - */ public function getProviderName(): string { return $this->providerName; } /** - * @param string $providerName * @return $this */ - public function setProviderName(string $providerName): TestCase + public function setProviderName(string $providerName): self { $this->providerName = $providerName; + return $this; } diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 755ba1047c1..95bfc1d20b2 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -14,6 +14,7 @@ use function get_debug_type; use function is_array; use function is_int; +use function is_iterable; use function is_string; use function sprintf; use PHPUnit\Event; @@ -80,8 +81,8 @@ public function providedData(string $className, string $methodName): ?array } /** - * @param class-string $testClassName Name of class with test - * @param non-empty-string $testMethodName Name of method containing test + * @param class-string $testClassName Name of class with test + * @param non-empty-string $testMethodName Name of method containing test * * @throws InvalidDataProviderException * @@ -97,7 +98,7 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod foreach ($dataProvider as $_dataProvider) { assert($_dataProvider instanceof DataProviderMetadata); - $providerClassName = $_dataProvider->className(); + $providerClassName = $_dataProvider->className(); $providerMethodName = $_dataProvider->methodName(); $dataProviderMethod = new ClassMethod($providerClassName, $providerMethodName); @@ -125,41 +126,47 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod } $data = $providerClassName::$providerMethodName(); + if (!is_iterable($data)) { $this->throwInvalid('does not provide iterable type', $_dataProvider); } } catch (Throwable $e) { $this->finishMethods($testMethod, $methodsCalled); + throw new InvalidDataProviderException( $e->getMessage(), $e->getCode(), $e, - $providerMethodName + $providerMethodName, ); } $result = []; + foreach ($data as $key => $value) { if (is_int($key)) { $result[] = $value; } elseif (is_string($key)) { if (isset($caseNames[$key])) { $this->finishMethods($testMethod, $methodsCalled); + throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous data provider', $key, - ), method: $providerMethodName + ), + method: $providerMethodName, ); } $caseNames[$key] = 1; - $result[$key] = $value; + $result[$key] = $value; } else { throw new InvalidDataProviderException( sprintf( 'The key must be an integer or a string, %s given', get_debug_type($key), - ), method: $providerMethodName + ), + method: $providerMethodName, ); } } @@ -170,12 +177,8 @@ private function dataProvidedByMethods(string $testClassName, string $testMethod return $return; } - /** - * @param string $message - * @param DataProviderMetadata $dataProvider - * @return never - */ - private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never { + private function throwInvalid(string $message, DataProviderMetadata $dataProvider): never + { throw new InvalidDataProviderException( sprintf( 'Data Provider method %s::%s() ', @@ -185,12 +188,8 @@ private function throwInvalid(string $message, DataProviderMetadata $dataProvide ); } - /** - * @param ClassMethod $method - * @param array $methodsCalled - * @return void - */ - private function finishMethods(ClassMethod $method, array $methodsCalled): void { + private function finishMethods(ClassMethod $method, array $methodsCalled): void + { Event\Facade::emitter()->dataProviderMethodFinished( $method, ...$methodsCalled, diff --git a/tests/_files/AbstractVariousIterableDataProviderTest.php b/tests/_files/AbstractVariousIterableDataProviderTest.php index 95ba6d8f214..d33270f6977 100644 --- a/tests/_files/AbstractVariousIterableDataProviderTest.php +++ b/tests/_files/AbstractVariousIterableDataProviderTest.php @@ -9,6 +9,7 @@ */ namespace PHPUnit\TestFixture; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; abstract class AbstractVariousIterableDataProviderTest @@ -22,7 +23,7 @@ public static function asArrayProviderInParent(): array ]; } - public static function asIteratorProviderInParent(): \Generator + public static function asIteratorProviderInParent(): Generator { yield ['M']; diff --git a/tests/unit/Metadata/Api/DataProviderTest.php b/tests/unit/Metadata/Api/DataProviderTest.php index ea4ac6eef86..104a928d098 100644 --- a/tests/unit/Metadata/Api/DataProviderTest.php +++ b/tests/unit/Metadata/Api/DataProviderTest.php @@ -43,9 +43,9 @@ public function testWithVariousIterableDataProvidersFromParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testFromParent'); $this->assertEquals([ - 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], - 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], - 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], + 'asArrayProviderInParent' => [['J'], ['K'], ['L']], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O']], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R']], ], $dataSets); } @@ -54,9 +54,9 @@ public function testWithVariousIterableDataProvidersInParent(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testInParent'); $this->assertEquals([ - 'asArrayProviderInParent' => [['J'], ['K'], ['L'],], - 'asIteratorProviderInParent' => [['M'], ['N'], ['O'],], - 'asTraversableProviderInParent' => [['P'], ['Q'], ['R'],], + 'asArrayProviderInParent' => [['J'], ['K'], ['L']], + 'asIteratorProviderInParent' => [['M'], ['N'], ['O']], + 'asTraversableProviderInParent' => [['P'], ['Q'], ['R']], ], $dataSets); } @@ -65,9 +65,9 @@ public function testWithVariousIterableAbstractDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testAbstract'); $this->assertEquals([ - 'asArrayProvider' => [['S'], ['T'], ['U'],], - 'asIteratorProvider' => [['V'], ['W'], ['X'],], - 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], + 'asArrayProvider' => [['S'], ['T'], ['U']], + 'asIteratorProvider' => [['V'], ['W'], ['X']], + 'asTraversableProvider' => [['Y'], ['Z'], ['P']], ], $dataSets); } @@ -76,9 +76,9 @@ public function testWithVariousIterableStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testStatic'); $this->assertEquals([ - 'asArrayStaticProvider' => [['A'], ['B'], ['C'],], - 'asIteratorStaticProvider' => [['D'], ['E'], ['F'],], - 'asTraversableStaticProvider' => [['G'], ['H'], ['I'],], + 'asArrayStaticProvider' => [['A'], ['B'], ['C']], + 'asIteratorStaticProvider' => [['D'], ['E'], ['F']], + 'asTraversableStaticProvider' => [['G'], ['H'], ['I']], ], $dataSets); } @@ -87,9 +87,9 @@ public function testWithVariousIterableNonStaticDataProviders(): void $dataSets = (new DataProvider)->providedData(VariousIterableDataProviderTest::class, 'testNonStatic'); $this->assertEquals([ - 'asArrayProvider' => [['S'], ['T'], ['U'],], - 'asIteratorProvider' => [['V'], ['W'], ['X'],], - 'asTraversableProvider' => [['Y'], ['Z'], ['P'],], + 'asArrayProvider' => [['S'], ['T'], ['U']], + 'asIteratorProvider' => [['V'], ['W'], ['X']], + 'asTraversableProvider' => [['Y'], ['Z'], ['P']], ], $dataSets); } @@ -138,12 +138,12 @@ public function checkMultipleProviders(string $testMethodName): void $this->assertCount(3, $dataSetsByProvider); $counts = ['a' => 0, 'b' => 0, 'c' => 0]; - $pos = ['a' => 0, 'b' => 1, 'c' => 2]; + $pos = ['a' => 0, 'b' => 1, 'c' => 2]; foreach ($dataSetsByProvider as $dataSet) { for ($i = 0; $i < 3; $i++) { foreach ($pos as $which => $where) { - if ($dataSet[$i][$where] !== null){ + if ($dataSet[$i][$where] !== null) { $counts[$which]++; } } From 39f0c2707abb555581509d500e3eb1e765f1c277 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Sun, 13 Oct 2024 19:36:38 +0200 Subject: [PATCH 09/11] make phpstan happy --- src/Metadata/Api/DataProvider.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 95bfc1d20b2..7e4d2d4dd0d 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -188,6 +188,9 @@ private function throwInvalid(string $message, DataProviderMetadata $dataProvide ); } + /** + * @param ClassMethod[] $methodsCalled + */ private function finishMethods(ClassMethod $method, array $methodsCalled): void { Event\Facade::emitter()->dataProviderMethodFinished( From c541273b13ebff0b6215891d1b7082b00ab6ea23 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Mon, 14 Oct 2024 18:57:12 +0200 Subject: [PATCH 10/11] adjust e2e --- src/Metadata/Api/DataProvider.php | 8 ++++++-- tests/end-to-end/event/data-provider-duplicate-key.phpt | 2 +- tests/end-to-end/event/data-provider-empty.phpt | 2 +- tests/end-to-end/event/data-provider-exception.phpt | 2 +- .../end-to-end/event/data-provider-expects-argument.phpt | 2 +- tests/end-to-end/event/data-provider-not-public.phpt | 2 +- tests/end-to-end/event/data-provider-not-static.phpt | 2 +- .../event/invalid-data-provider-with-passing-test.phpt | 2 +- tests/end-to-end/event/invalid-data-provider.phpt | 2 +- tests/end-to-end/regression/2137-filter.phpt | 4 ++-- tests/end-to-end/regression/2137-no_filter.phpt | 4 ++-- tests/end-to-end/regression/498.phpt | 2 +- tests/end-to-end/regression/5138.phpt | 2 +- tests/end-to-end/regression/5451.phpt | 2 +- tests/end-to-end/regression/5908-list-tests-xml.phpt | 2 +- tests/end-to-end/regression/5908-list-tests.phpt | 2 +- tests/end-to-end/regression/765.phpt | 2 +- 17 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/Metadata/Api/DataProvider.php b/src/Metadata/Api/DataProvider.php index 7e4d2d4dd0d..9f4cb479e3b 100644 --- a/src/Metadata/Api/DataProvider.php +++ b/src/Metadata/Api/DataProvider.php @@ -16,6 +16,8 @@ use function is_int; use function is_iterable; use function is_string; +use function key; +use function reset; use function sprintf; use PHPUnit\Event; use PHPUnit\Event\Code\ClassMethod; @@ -57,13 +59,14 @@ public function providedData(string $className, string $methodName): ?array $data = ['testWith' => $this->dataProvidedByMetadata($testWith)]; } - if ($data === [] || $data === ['testWith' => []]) { + if ($data === [] || reset($data) === []) { throw new InvalidDataProviderException( 'Empty data set provided by data provider', + method: key($data), ); } - foreach ($data as $providedData) { + foreach ($data as $providerMethodName => $providedData) { foreach ($providedData as $key => $value) { if (!is_array($value)) { throw new InvalidDataProviderException( @@ -72,6 +75,7 @@ public function providedData(string $className, string $methodName): ?array is_int($key) ? '#' . $key : '"' . $key . '"', get_debug_type($value), ), + method: $providerMethodName, ); } } diff --git a/tests/end-to-end/event/data-provider-duplicate-key.phpt b/tests/end-to-end/event/data-provider-duplicate-key.phpt index 0bc07706d78..99c8b923995 100644 --- a/tests/end-to-end/event/data-provider-duplicate-key.phpt +++ b/tests/end-to-end/event/data-provider-duplicate-key.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\DataProviderDuplicateKeyT Data Provider Method Finished for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething: - PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething) -The data provider specified for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest::testSomething is invalid The key "key" has already been defined by a previous data provider Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\DataProviderDuplicateKeyTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-empty.phpt b/tests/end-to-end/event/data-provider-empty.phpt index 83c6f4c54af..1285cff66b5 100644 --- a/tests/end-to-end/event/data-provider-empty.phpt +++ b/tests/end-to-end/event/data-provider-empty.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\EmptyDataProviderTest::pr Data Provider Method Finished for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase: - PHPUnit\TestFixture\Event\EmptyDataProviderTest::providerMethod Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase) -The data provider specified for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase is invalid +The data provider providerMethod specified for PHPUnit\TestFixture\Event\EmptyDataProviderTest::testCase is invalid Empty data set provided by data provider Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\EmptyDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-exception.phpt b/tests/end-to-end/event/data-provider-exception.phpt index fc4f1dd5203..d99de4633f3 100644 --- a/tests/end-to-end/event/data-provider-exception.phpt +++ b/tests/end-to-end/event/data-provider-exception.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\ExceptionInDataProviderTe Data Provider Method Finished for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne: - PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\ExceptionInDataProviderTest::testOne is invalid message Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\ExceptionInDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-expects-argument.phpt b/tests/end-to-end/event/data-provider-expects-argument.phpt index 3616bc7ec40..a139386d62f 100644 --- a/tests/end-to-end/event/data-provider-expects-argument.phpt +++ b/tests/end-to-end/event/data-provider-expects-argument.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\ArgumentDataProviderTest: Data Provider Method Finished for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\ArgumentDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\ArgumentDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\ArgumentDataProviderTest::values() expects an argument Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\ArgumentDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-not-public.phpt b/tests/end-to-end/event/data-provider-not-public.phpt index eaa601f8dc9..7d8649bfe5b 100644 --- a/tests/end-to-end/event/data-provider-not-public.phpt +++ b/tests/end-to-end/event/data-provider-not-public.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\PrivateDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\PrivateDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\PrivateDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\PrivateDataProviderTest::values() is not public Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\PrivateDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/data-provider-not-static.phpt b/tests/end-to-end/event/data-provider-not-static.phpt index 88916b9b939..ac34cfedeb7 100644 --- a/tests/end-to-end/event/data-provider-not-static.phpt +++ b/tests/end-to-end/event/data-provider-not-static.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\DynamicDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess: - PHPUnit\TestFixture\Event\DynamicDataProviderTest::values Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess) -The data provider specified for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess is invalid +The data provider values specified for PHPUnit\TestFixture\Event\DynamicDataProviderTest::testSuccess is invalid Data Provider method PHPUnit\TestFixture\Event\DynamicDataProviderTest::values() is not static Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\DynamicDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt b/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt index 848ed0a3f54..bbbb883eb1d 100644 --- a/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt +++ b/tests/end-to-end/event/invalid-data-provider-with-passing-test.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\InvalidDataProviderWithOn Data Provider Method Finished for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne: - PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderWithOneTestPassingTest::testOne is invalid Data set #0 is invalid, expected array but got int Test Suite Loaded (1 test) Test Runner Started diff --git a/tests/end-to-end/event/invalid-data-provider.phpt b/tests/end-to-end/event/invalid-data-provider.phpt index 48a8e9e8e35..6726dfb4872 100644 --- a/tests/end-to-end/event/invalid-data-provider.phpt +++ b/tests/end-to-end/event/invalid-data-provider.phpt @@ -18,7 +18,7 @@ Data Provider Method Called (PHPUnit\TestFixture\Event\InvalidDataProviderTest:: Data Provider Method Finished for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne: - PHPUnit\TestFixture\Event\InvalidDataProviderTest::provider Test Triggered PHPUnit Error (PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne) -The data provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Event\InvalidDataProviderTest::testOne is invalid Data set #0 is invalid, expected array but got int Test Runner Triggered Warning (No tests found in class "PHPUnit\TestFixture\Event\InvalidDataProviderTest".) Test Suite Loaded (0 tests) diff --git a/tests/end-to-end/regression/2137-filter.phpt b/tests/end-to-end/regression/2137-filter.phpt index 7b56bcda1c4..df3f3fb7eb8 100644 --- a/tests/end-to-end/regression/2137-filter.phpt +++ b/tests/end-to-end/regression/2137-filter.phpt @@ -18,13 +18,13 @@ Runtime: %s There were 2 PHPUnit errors: 1) PHPUnit\TestFixture\Issue2137Test::testBrandService -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid Data set #0 is invalid, expected array but got stdClass %s:%d 2) PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid Data set #0 is invalid, expected array but got stdClass %s:%d diff --git a/tests/end-to-end/regression/2137-no_filter.phpt b/tests/end-to-end/regression/2137-no_filter.phpt index 2f68ffbbfaf..574ad18c4fc 100644 --- a/tests/end-to-end/regression/2137-no_filter.phpt +++ b/tests/end-to-end/regression/2137-no_filter.phpt @@ -16,13 +16,13 @@ Runtime: %s There were 2 PHPUnit errors: 1) PHPUnit\TestFixture\Issue2137Test::testBrandService -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testBrandService is invalid Data set #0 is invalid, expected array but got stdClass %s:%d 2) PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid -The data provider specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid +The data provider provideBrandService specified for PHPUnit\TestFixture\Issue2137Test::testSomethingElseInvalid is invalid Data set #0 is invalid, expected array but got stdClass %s:%d diff --git a/tests/end-to-end/regression/498.phpt b/tests/end-to-end/regression/498.phpt index eb69c45f5d3..432752a92a6 100644 --- a/tests/end-to-end/regression/498.phpt +++ b/tests/end-to-end/regression/498.phpt @@ -18,7 +18,7 @@ Runtime: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue498Test::shouldBeFalse -The data provider specified for PHPUnit\TestFixture\Issue498Test::shouldBeFalse is invalid +The data provider shouldBeFalseDataProvider specified for PHPUnit\TestFixture\Issue498Test::shouldBeFalse is invalid Can't create the data %s:%d diff --git a/tests/end-to-end/regression/5138.phpt b/tests/end-to-end/regression/5138.phpt index 5675237ee26..6038cb68e18 100644 --- a/tests/end-to-end/regression/5138.phpt +++ b/tests/end-to-end/regression/5138.phpt @@ -17,7 +17,7 @@ Configuration: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue5138Test::testOne -The data provider specified for PHPUnit\TestFixture\Issue5138Test::testOne is invalid +The data provider provideData specified for PHPUnit\TestFixture\Issue5138Test::testOne is invalid message %s:%d diff --git a/tests/end-to-end/regression/5451.phpt b/tests/end-to-end/regression/5451.phpt index 942cf44bf21..a19798eea6f 100644 --- a/tests/end-to-end/regression/5451.phpt +++ b/tests/end-to-end/regression/5451.phpt @@ -25,7 +25,7 @@ Time: %s, Memory: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider -The data provider specified for PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider is invalid +The data provider dataProviderThatTriggersPhpError specified for PHPUnit\TestFixture\Issue5451\Issue5451Test::testWithErrorInDataProvider is invalid Call to a member function bar() on array %s%eIssue5451Test.php:26 diff --git a/tests/end-to-end/regression/5908-list-tests-xml.phpt b/tests/end-to-end/regression/5908-list-tests-xml.phpt index d4034071955..e12efe28bf0 100644 --- a/tests/end-to-end/regression/5908-list-tests-xml.phpt +++ b/tests/end-to-end/regression/5908-list-tests-xml.phpt @@ -20,5 +20,5 @@ PHPUnit %s by Sebastian Bergmann and contributors. There were errors: -The data provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid message diff --git a/tests/end-to-end/regression/5908-list-tests.phpt b/tests/end-to-end/regression/5908-list-tests.phpt index 88757a15215..6b759e7b2d3 100644 --- a/tests/end-to-end/regression/5908-list-tests.phpt +++ b/tests/end-to-end/regression/5908-list-tests.phpt @@ -15,5 +15,5 @@ PHPUnit %s by Sebastian Bergmann and contributors. There were errors: -The data provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid +The data provider provider specified for PHPUnit\TestFixture\Issue5908\Issue5908Test::testOne is invalid message diff --git a/tests/end-to-end/regression/765.phpt b/tests/end-to-end/regression/765.phpt index 0aac3d9e8d1..e4e958fc9fe 100644 --- a/tests/end-to-end/regression/765.phpt +++ b/tests/end-to-end/regression/765.phpt @@ -25,7 +25,7 @@ Time: %s, Memory: %s There was 1 PHPUnit error: 1) PHPUnit\TestFixture\Issue765Test::testDependent -The data provider specified for PHPUnit\TestFixture\Issue765Test::testDependent is invalid +The data provider dependentProvider specified for PHPUnit\TestFixture\Issue765Test::testDependent is invalid %s:%d From f05f43d1256119b37346c53e7383b63c7898a8f9 Mon Sep 17 00:00:00 2001 From: AdamPDotty Date: Tue, 15 Oct 2024 18:02:43 +0200 Subject: [PATCH 11/11] cover exception when provider key is of wrong type; cover function TestCase::getProviderName() --- tests/_files/DuplicateKeyDataProviderTest.php | 2 +- .../_files/DuplicateKeyDataProvidersTest.php | 2 +- tests/_files/InvalidKeyDataProviderTest.php | 29 +++++++++++++++++++ tests/unit/Framework/TestCaseTest.php | 8 +++++ tests/unit/Metadata/Api/DataProviderTest.php | 12 +++++++- 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/_files/InvalidKeyDataProviderTest.php diff --git a/tests/_files/DuplicateKeyDataProviderTest.php b/tests/_files/DuplicateKeyDataProviderTest.php index 60568a9c732..1d72dd1935c 100644 --- a/tests/_files/DuplicateKeyDataProviderTest.php +++ b/tests/_files/DuplicateKeyDataProviderTest.php @@ -23,7 +23,7 @@ public static function dataProvider(): Generator } #[DataProvider('dataProvider')] - public function test($arg): void + public function test(string $arg): void { } } diff --git a/tests/_files/DuplicateKeyDataProvidersTest.php b/tests/_files/DuplicateKeyDataProvidersTest.php index a44c5578449..4f76545175d 100644 --- a/tests/_files/DuplicateKeyDataProvidersTest.php +++ b/tests/_files/DuplicateKeyDataProvidersTest.php @@ -30,7 +30,7 @@ public static function dataProvider2(): iterable #[DataProvider('dataProvider1')] #[DataProvider('dataProvider2')] - public function test($value): void + public function test(int $value): void { $this->assertSame(2, $value); } diff --git a/tests/_files/InvalidKeyDataProviderTest.php b/tests/_files/InvalidKeyDataProviderTest.php new file mode 100644 index 00000000000..b468cf31de1 --- /dev/null +++ b/tests/_files/InvalidKeyDataProviderTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestFixture; + +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; + +final class InvalidKeyDataProviderTest extends TestCase +{ + public static function dataProvider(): Generator + { + yield true => [true]; + + yield false => [false]; + } + + #[DataProvider('dataProvider')] + public function test(bool $arg): void + { + } +} diff --git a/tests/unit/Framework/TestCaseTest.php b/tests/unit/Framework/TestCaseTest.php index fe940bfb802..6086d37c516 100644 --- a/tests/unit/Framework/TestCaseTest.php +++ b/tests/unit/Framework/TestCaseTest.php @@ -11,7 +11,9 @@ use function sprintf; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProviderExternal; use PHPUnit\Framework\Attributes\ExcludeGlobalVariableFromBackup; +use PHPUnit\TestFixture\TestBuilder\TestWithDataProvider; use PHPUnit\TestFixture\TestWithDifferentNames; #[CoversClass(TestCase::class)] @@ -83,4 +85,10 @@ public function testGetNameReturnsMethodName(): void $this->assertSame($methodName, $testCase->nameWithDataSet()); } + + #[DataProviderExternal(TestWithDataProvider::class, 'provider')] + public function testKnowProviderName(): void + { + $this->assertEquals('provider', $this->getProviderName()); + } } diff --git a/tests/unit/Metadata/Api/DataProviderTest.php b/tests/unit/Metadata/Api/DataProviderTest.php index 104a928d098..4ee95fdd7ae 100644 --- a/tests/unit/Metadata/Api/DataProviderTest.php +++ b/tests/unit/Metadata/Api/DataProviderTest.php @@ -16,6 +16,7 @@ use PHPUnit\Framework\TestCase; use PHPUnit\TestFixture\DuplicateKeyDataProvidersTest; use PHPUnit\TestFixture\DuplicateKeyDataProviderTest; +use PHPUnit\TestFixture\InvalidKeyDataProviderTest; use PHPUnit\TestFixture\MultipleDataProviderTest; use PHPUnit\TestFixture\TestWithAttributeDataProviderTest; use PHPUnit\TestFixture\VariousIterableDataProviderTest; @@ -93,6 +94,15 @@ public function testWithVariousIterableNonStaticDataProviders(): void ], $dataSets); } + public function testWithInvalidKeyDataProvider(): void + { + $this->expectException(InvalidDataProviderException::class); + $this->expectExceptionMessage('The key must be an integer or a string, bool given'); + + /* @noinspection UnusedFunctionResultInspection */ + (new DataProvider)->providedData(InvalidKeyDataProviderTest::class, 'test'); + } + public function testWithDuplicateKeyDataProvider(): void { $this->expectException(InvalidDataProviderException::class); @@ -132,7 +142,7 @@ public function testWithDuplicateKeyDataProviders(): void (new DataProvider)->providedData(DuplicateKeyDataProvidersTest::class, 'test'); } - public function checkMultipleProviders(string $testMethodName): void + private function checkMultipleProviders(string $testMethodName): void { $dataSetsByProvider = (new DataProvider)->providedData(MultipleDataProviderTest::class, $testMethodName); $this->assertCount(3, $dataSetsByProvider);