mirror of
https://github.com/danog/psalm-plugin-phpunit.git
synced 2024-12-02 09:27:56 +01:00
Merge pull request #24 from weirdan/variadic-tests
Support variadics in test methods
This commit is contained in:
commit
e33ae73dc7
@ -231,10 +231,14 @@ class TestCaseHandler implements
|
||||
}
|
||||
|
||||
$checkParam =
|
||||
/** @return void */
|
||||
/**
|
||||
* @param null|Type\Union $param_default_type
|
||||
* @return void
|
||||
*/
|
||||
function (
|
||||
Type\Union $potential_argument_type,
|
||||
FunctionLikeParameter $param,
|
||||
Type\Union $param_type,
|
||||
$param_default_type,
|
||||
int $param_offset
|
||||
) use (
|
||||
$codebase,
|
||||
@ -243,9 +247,8 @@ class TestCaseHandler implements
|
||||
$provider_return_type_string,
|
||||
$provider_docblock_location
|
||||
) {
|
||||
assert(null !== $param->type);
|
||||
$param_type = clone $param->type;
|
||||
if ($param->default_type) {
|
||||
$param_type = clone $param_type;
|
||||
if ($param_default_type) {
|
||||
$param_type->possibly_undefined = true;
|
||||
}
|
||||
if (self::isTypeContainedByType($codebase, $potential_argument_type, $param_type)) {
|
||||
@ -258,7 +261,7 @@ class TestCaseHandler implements
|
||||
. ' by ' . $provider_method_id . '():(' . $provider_return_type_string . ')',
|
||||
$provider_docblock_location
|
||||
));
|
||||
} elseif ($potential_argument_type->possibly_undefined && !$param->default_type) {
|
||||
} elseif ($potential_argument_type->possibly_undefined && !$param_default_type) {
|
||||
IssueBuffer::accepts(new Issue\InvalidArgument(
|
||||
'Argument ' . ($param_offset + 1) . ' of ' . $method_name
|
||||
. ' has no default value, but possibly undefined '
|
||||
@ -284,32 +287,60 @@ class TestCaseHandler implements
|
||||
// check that all of the required (?) params accept value type
|
||||
$potential_argument_type = $dataset_type->type_params[1];
|
||||
foreach ($method_storage->params as $param_offset => $param) {
|
||||
$checkParam($potential_argument_type, $param, $param_offset);
|
||||
assert(null !== $param->type);
|
||||
$checkParam($potential_argument_type, $param->type, $param->default_type, $param_offset);
|
||||
}
|
||||
} else {
|
||||
// iterate over all params checking if corresponding value type is acceptable
|
||||
// let's hope properties are sorted in array order
|
||||
$potential_argument_types = array_values($dataset_type->properties);
|
||||
|
||||
if (count($potential_argument_types) < $method_storage->required_param_count) {
|
||||
foreach ($method_storage->params as $param_offset => $param) {
|
||||
if (!isset($potential_argument_types[$param_offset])) {
|
||||
// variadics are never required
|
||||
// and they always come last
|
||||
if ($param->is_variadic) {
|
||||
break;
|
||||
}
|
||||
// reached default params, so it's fine, but let's continue
|
||||
// because MisplacedRequiredParam could be suppressed
|
||||
if ($param->default_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IssueBuffer::accepts(new Issue\TooFewArguments(
|
||||
'Too few arguments for ' . $method_name
|
||||
. ' - expecting ' . $method_storage->required_param_count
|
||||
. ' but saw ' . count($potential_argument_types)
|
||||
. ' - expecting at least ' . ($param_offset + 1)
|
||||
. ', but saw ' . count($potential_argument_types)
|
||||
. ' provided by ' . $provider_method_id . '()'
|
||||
. ':(' . $provider_return_type_string . ')',
|
||||
$provider_docblock_location,
|
||||
$method_name
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($method_storage->params as $param_offset => $param) {
|
||||
if (!isset($potential_argument_types[$param_offset])) {
|
||||
break;
|
||||
}
|
||||
$potential_argument_type = $potential_argument_types[$param_offset];
|
||||
|
||||
$checkParam($potential_argument_type, $param, $param_offset);
|
||||
assert(null !== $param->type);
|
||||
if ($param->is_variadic) {
|
||||
/** @var Type\Atomic\TArray $variadic_type */
|
||||
$variadic_type = $param->type->getTypes()['array'];
|
||||
$variadic_param_type = $variadic_type->type_params[1] ?? Type::getMixed();
|
||||
|
||||
// check remaining argument types
|
||||
for (; $param_offset < count($potential_argument_types); $param_offset++) {
|
||||
$potential_argument_type = $potential_argument_types[$param_offset];
|
||||
$checkParam(
|
||||
$potential_argument_type,
|
||||
$variadic_param_type,
|
||||
$variadic_param_type,
|
||||
$param_offset
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$checkParam($potential_argument_type, $param->type, $param->default_type, $param_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -470,7 +470,7 @@ Feature: TestCase
|
||||
When I run Psalm
|
||||
Then I see these errors
|
||||
| Type | Message |
|
||||
| TooFewArguments | Too few arguments for NS\MyTestCase::testSomething - expecting 2 but saw 1 provided by NS\MyTestCase::provide():(iterable<string, array{0:int}>) |
|
||||
| TooFewArguments | Too few arguments for NS\MyTestCase::testSomething - expecting at least 2, but saw 1 provided by NS\MyTestCase::provide():(iterable<string, array{0:int}>) |
|
||||
And I see no other errors
|
||||
|
||||
Scenario: Referenced providers are not marked as unused
|
||||
@ -857,3 +857,81 @@ Feature: TestCase
|
||||
| Type | Message |
|
||||
| InvalidArgument | Argument 1 of NS\MyTestTrait::testSomething expects string, int provided by NS\MyTestTrait::provide():(iterable<int, array<array-key, int>>) |
|
||||
And I see no other errors
|
||||
|
||||
Scenario: Providers may omit variadic part for variadic tests
|
||||
Given I have the following code
|
||||
"""
|
||||
class MyTestCase extends TestCase {
|
||||
/** @return iterable<string,array{int}> */
|
||||
public function provide() {
|
||||
yield "data set" => [1];
|
||||
}
|
||||
/**
|
||||
* @dataProvider provide
|
||||
* @return void
|
||||
*/
|
||||
public function testSomething(int $i, ...$rest) {}
|
||||
}
|
||||
"""
|
||||
When I run Psalm
|
||||
Then I see no errors
|
||||
|
||||
Scenario: Providers may omit non-varidic params with default for variadic tests
|
||||
Given I have the following code
|
||||
"""
|
||||
class MyTestCase extends TestCase {
|
||||
/** @return iterable<string,array{int}> */
|
||||
public function provide() {
|
||||
yield "data set" => [1];
|
||||
}
|
||||
/**
|
||||
* @dataProvider provide
|
||||
* @return void
|
||||
*/
|
||||
public function testSomething(int $i, string $s = "", ...$rest) {}
|
||||
}
|
||||
"""
|
||||
When I run Psalm
|
||||
Then I see no errors
|
||||
|
||||
Scenario: Providers may not omit non-varidic params with no default for variadic tests
|
||||
Given I have the following code
|
||||
"""
|
||||
class MyTestCase extends TestCase {
|
||||
/** @return iterable<string,array{int}> */
|
||||
public function provide() {
|
||||
yield "data set" => [1];
|
||||
}
|
||||
/**
|
||||
* @dataProvider provide
|
||||
* @return void
|
||||
*/
|
||||
public function testSomething(int $i, string $s, ...$rest) {}
|
||||
}
|
||||
"""
|
||||
When I run Psalm
|
||||
Then I see these errors
|
||||
| Type | Message |
|
||||
| TooFewArguments | Too few arguments for NS\MyTestCase::testSomething - expecting at least 2, but saw 1 provided by NS\MyTestCase::provide():(iterable<string, array{0:int}>) |
|
||||
And I see no other errors
|
||||
|
||||
Scenario: Providers generating incompatible datasets for variadic tests are reported
|
||||
Given I have the following code
|
||||
"""
|
||||
class MyTestCase extends TestCase {
|
||||
/** @return iterable<string,array{float,1?:string}> */
|
||||
public function provide() {
|
||||
yield "data set" => [1., "a"];
|
||||
}
|
||||
/**
|
||||
* @dataProvider provide
|
||||
* @return void
|
||||
*/
|
||||
public function testSomething(float ...$rest) {}
|
||||
}
|
||||
"""
|
||||
When I run Psalm
|
||||
Then I see these errors
|
||||
| Type | Message |
|
||||
| InvalidArgument | Argument 2 of NS\MyTestCase::testSomething expects float, string provided by NS\MyTestCase::provide():(iterable<string, array{0:float, 1?:string}>) |
|
||||
And I see no other errors
|
||||
|
Loading…
Reference in New Issue
Block a user