Skip to content

Commit 033f690

Browse files
authored
PHPUnit 9.x/10.x does not at all support named arguments from data-providers
1 parent 758d343 commit 033f690

File tree

4 files changed

+144
-31
lines changed

4 files changed

+144
-31
lines changed

src/Rules/PHPUnit/DataProviderDataRule.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ class DataProviderDataRule implements Rule
2323

2424
private DataProviderHelper $dataProviderHelper;
2525

26+
private PHPUnitVersion $PHPUnitVersion;
27+
2628
public function __construct(
2729
TestMethodsHelper $testMethodsHelper,
28-
DataProviderHelper $dataProviderHelper
30+
DataProviderHelper $dataProviderHelper,
31+
PHPUnitVersion $PHPUnitVersion
2932
)
3033
{
3134
$this->testMethodsHelper = $testMethodsHelper;
3235
$this->dataProviderHelper = $dataProviderHelper;
36+
$this->PHPUnitVersion = $PHPUnitVersion;
3337
}
3438

3539
public function getNodeType(): string
@@ -153,11 +157,10 @@ private function arrayItemsToArgs(Type $array, int $numberOfParameters): ?array
153157
return null;
154158
}
155159

156-
if (count($key) === 0) {
160+
if (count($key) === 0 || !$this->PHPUnitVersion->supportsNamedArgumentsInDataProvider()->yes()) {
157161
$arg = new Node\Arg(new TypeExpr($valueType));
158162
$args[] = $arg;
159163
continue;
160-
161164
}
162165

163166
$arg = new Node\Arg(

src/Rules/PHPUnit/PHPUnitVersion.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,12 @@ public function requiresStaticDataProviders(): TrinaryLogic
3838
return TrinaryLogic::createFromBoolean($this->majorVersion >= 10);
3939
}
4040

41+
public function supportsNamedArgumentsInDataProvider(): TrinaryLogic
42+
{
43+
if ($this->majorVersion === null) {
44+
return TrinaryLogic::createMaybe();
45+
}
46+
return TrinaryLogic::createFromBoolean($this->majorVersion >= 11);
47+
}
48+
4149
}

tests/Rules/PHPUnit/DataProviderDataRuleTest.php

Lines changed: 98 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,36 @@
88
use PHPStan\Rules\Rule;
99
use PHPStan\Testing\RuleTestCase;
1010
use PHPStan\Type\FileTypeMapper;
11+
use PHPUnit\Framework\Attributes\DataProvider;
12+
use PHPUnit\Framework\Attributes\TestWith;
13+
use const PHP_VERSION_ID;
1114

1215
/**
1316
* @extends RuleTestCase<CompositeRule>
1417
*/
1518
class DataProviderDataRuleTest extends RuleTestCase
1619
{
17-
private int $phpunitVersion;
20+
private ?int $phpunitVersion;
1821

1922
protected function getRule(): Rule
2023
{
2124
$reflectionProvider = $this->createReflectionProvider();
25+
$phpunitVersion = new PHPUnitVersion($this->phpunitVersion);
2226

2327
/** @var list<Rule<Node>> $rules */
2428
$rules = [
2529
new DataProviderDataRule(
2630
new TestMethodsHelper(
2731
self::getContainer()->getByType(FileTypeMapper::class),
28-
new PHPUnitVersion($this->phpunitVersion)
32+
$phpunitVersion
2933
),
3034
new DataProviderHelper(
3135
$reflectionProvider,
3236
self::getContainer()->getByType(FileTypeMapper::class),
3337
self::getContainer()->getService('defaultAnalysisParser'),
34-
new PHPUnitVersion($this->phpunitVersion)
38+
$phpunitVersion
3539
),
36-
40+
$phpunitVersion,
3741
),
3842
self::getContainer()->getByType(CallMethodsRule::class) /** @phpstan-ignore phpstanApi.classConstant */
3943
];
@@ -173,36 +177,64 @@ public function testRule(): void
173177
]);
174178
}
175179

176-
public function testRulePhp8(): void
180+
181+
/**
182+
* @dataProvider provideNamedArgumentPHPUnitVersions
183+
*/
184+
#[DataProvider('provideNamedArgumentPHPUnitVersions')]
185+
public function testRulePhp8(?int $phpunitVersion): void
177186
{
178187
if (PHP_VERSION_ID < 80000) {
179188
self::markTestSkipped();
180189
}
181190

182-
$this->phpunitVersion = 10;
191+
$this->phpunitVersion = $phpunitVersion;
183192

184-
$this->analyse([__DIR__ . '/data/data-provider-data-named.php'], [
185-
[
186-
'Parameter $input of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, int given.',
187-
44
188-
],
189-
[
190-
'Parameter $input of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, false given.',
191-
44
192-
],
193-
[
194-
'Unknown parameter $wrong in call to method DataProviderDataTestPhp8\TestWrongOffsetNameArrayShapeIterable::testBar().',
195-
58
196-
],
197-
[
198-
'Missing parameter $si (int) in call to method DataProviderDataTestPhp8\TestWrongOffsetNameArrayShapeIterable::testBar().',
199-
58
200-
],
201-
[
202-
'Parameter $si of method DataProviderDataTestPhp8\TestWrongTypeInArrayShapeIterable::testBar() expects int, string given.',
203-
79
204-
],
205-
]);
193+
if ($phpunitVersion >= 11) {
194+
$errors = [
195+
[
196+
'Parameter $input of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, int given.',
197+
44
198+
],
199+
[
200+
'Parameter $input of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, false given.',
201+
44
202+
],
203+
[
204+
'Unknown parameter $wrong in call to method DataProviderDataTestPhp8\TestWrongOffsetNameArrayShapeIterable::testBar().',
205+
58
206+
],
207+
[
208+
'Missing parameter $si (int) in call to method DataProviderDataTestPhp8\TestWrongOffsetNameArrayShapeIterable::testBar().',
209+
58
210+
],
211+
[
212+
'Parameter $si of method DataProviderDataTestPhp8\TestWrongTypeInArrayShapeIterable::testBar() expects int, string given.',
213+
79
214+
],
215+
];
216+
} else {
217+
$errors = [
218+
[
219+
'Parameter #1 $expectedResult of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, int given.',
220+
44
221+
],
222+
[
223+
'Parameter #1 $expectedResult of method DataProviderDataTestPhp8\NamedArgsInProvider::testFoo() expects string, false given.',
224+
44
225+
],
226+
[
227+
'Parameter #1 $si of method DataProviderDataTestPhp8\TestWrongOffsetNameArrayShapeIterable::testBar() expects int, string given.',
228+
58
229+
],
230+
[
231+
'Parameter #1 $si of method DataProviderDataTestPhp8\TestWrongTypeInArrayShapeIterable::testBar() expects int, string given.',
232+
79
233+
],
234+
];
235+
}
236+
237+
$this->analyse([__DIR__ . '/data/data-provider-data-named.php'], $errors);
206238
}
207239

208240

@@ -274,6 +306,44 @@ public function testTrimmingArgs(): void
274306
]);
275307
}
276308

309+
static public function provideNamedArgumentPHPUnitVersions(): iterable
310+
{
311+
yield [null]; // unknown phpunit version
312+
313+
if (PHP_VERSION_ID >= 80100) {
314+
yield [10]; // PHPUnit 10.x requires PHP 8.1+
315+
}
316+
if (PHP_VERSION_ID >= 80200) {
317+
yield [11]; // PHPUnit 11.x requires PHP 8.2+
318+
}
319+
}
320+
321+
/**
322+
* @dataProvider provideNamedArgumentPHPUnitVersions
323+
*/
324+
#[DataProvider('provideNamedArgumentPHPUnitVersions')]
325+
public function testNamedArgumentsInDataProviders(?int $phpunitVersion): void
326+
{
327+
$this->phpunitVersion = $phpunitVersion;
328+
329+
if ($phpunitVersion >= 11) {
330+
$errors = [];
331+
} else {
332+
$errors = [
333+
[
334+
'Parameter #1 $int of method DataProviderNamedArgs\FooTest::testFoo() expects int, string given.',
335+
26
336+
],
337+
[
338+
'Parameter #2 $string of method DataProviderNamedArgs\FooTest::testFoo() expects string, int given.',
339+
26
340+
],
341+
];
342+
}
343+
344+
$this->analyse([__DIR__ . '/data/data-provider-named-args.php'], $errors);
345+
}
346+
277347
/**
278348
* @return string[]
279349
*/
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace DataProviderNamedArgs;
4+
5+
class FooTest extends \PHPUnit\Framework\TestCase
6+
{
7+
8+
/**
9+
* @dataProvider dataProvider
10+
*/
11+
public function testFoo(
12+
int $int,
13+
string $string
14+
): void
15+
{
16+
$this->assertTrue(true);
17+
}
18+
19+
public static function dataProvider(): iterable
20+
{
21+
yield 'even' => [
22+
'int' => 50,
23+
'string' => 'abc',
24+
];
25+
26+
yield 'odd' => [
27+
'string' => 'def',
28+
'int' => 51,
29+
];
30+
}
31+
}
32+

0 commit comments

Comments
 (0)