2019-02-10 07:19:06 +01:00
|
|
|
Feature: Assert (PHPUnit 7.5+)
|
|
|
|
In order to use PHPUnit safely
|
|
|
|
As a Psalm user
|
|
|
|
I need Psalm to typecheck asserts
|
|
|
|
|
|
|
|
Background:
|
2019-02-18 15:19:30 +01:00
|
|
|
Given I have the following config
|
|
|
|
"""
|
|
|
|
<?xml version="1.0"?>
|
|
|
|
<psalm>
|
|
|
|
<projectFiles><directory name="." /></projectFiles>
|
|
|
|
<plugins>
|
|
|
|
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
|
|
|
|
</plugins>
|
|
|
|
</psalm>
|
|
|
|
"""
|
|
|
|
And I have the following code preamble
|
2019-02-10 07:19:06 +01:00
|
|
|
"""
|
|
|
|
<?php
|
|
|
|
namespace NS;
|
|
|
|
use PHPUnit\Framework\Assert;
|
|
|
|
|
2019-06-29 23:00:39 +02:00
|
|
|
/**
|
|
|
|
* @return mixed
|
2019-02-10 07:19:06 +01:00
|
|
|
* @psalm-suppress InvalidReturnType
|
|
|
|
*/
|
|
|
|
function mixed() {}
|
|
|
|
|
|
|
|
"""
|
|
|
|
And I have PHPUnit newer than "7.4.99999" (because of "new features in 7.5")
|
|
|
|
|
2020-04-05 20:33:48 +02:00
|
|
|
Scenario: Assert::assertInstanceOf()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
function f(): \Exception {
|
|
|
|
return rand(0,1) ? new \RuntimeException : new \InvalidArgumentException;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
function acceptsRuntimeException(\RuntimeException $_e) {}
|
|
|
|
|
|
|
|
$e = f();
|
|
|
|
Assert::assertInstanceOf(\RuntimeException::class, $e);
|
|
|
|
acceptsRuntimeException($e);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
2019-02-10 07:19:06 +01:00
|
|
|
Scenario: Assert::assertIsArray()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$a = mixed();
|
|
|
|
Assert::assertIsArray($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsBool()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$b = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsBool($b);
|
2019-06-29 23:00:39 +02:00
|
|
|
class_exists(Assert::class, $b);
|
2019-02-10 07:19:06 +01:00
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsFloat()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$f = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsFloat($f);
|
|
|
|
atan($f);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsInt()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$i = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsInt($i);
|
|
|
|
substr('foo', $i);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNumeric()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$n = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsNumeric($n);
|
|
|
|
$n + $n;
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsObject()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$o = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsObject($o);
|
|
|
|
$o->foo = 1;
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsResource()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$r = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsResource($r);
|
|
|
|
get_resource_type($r);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsString()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$s = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsString($s);
|
|
|
|
strlen($s);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsScalar()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
2020-03-30 03:47:58 +02:00
|
|
|
/** @return scalar */
|
|
|
|
function f() {
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$s = mixed();
|
2019-02-10 07:19:06 +01:00
|
|
|
|
2020-03-30 03:47:58 +02:00
|
|
|
Assert::assertIsScalar($s);
|
|
|
|
return $s;
|
|
|
|
}
|
2019-02-10 07:19:06 +01:00
|
|
|
"""
|
|
|
|
When I run Psalm
|
2020-03-30 03:47:58 +02:00
|
|
|
Then I see no errors
|
2019-02-10 07:19:06 +01:00
|
|
|
|
|
|
|
Scenario: Assert::assertIsCallable()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$s = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsCallable($s);
|
|
|
|
\Closure::fromCallable($s);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsIterable()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @return iterable */
|
|
|
|
function () {
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$s = mixed();
|
|
|
|
|
|
|
|
Assert::assertIsIterable($s);
|
|
|
|
return $s;
|
|
|
|
};
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotArray()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$i = rand(0, 1) ? 1 : [1];
|
|
|
|
Assert::assertIsNotArray($i);
|
|
|
|
substr("foo", $i);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotBool()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$i = rand(0, 1) ? 1 : true;
|
|
|
|
Assert::assertIsNotBool($i);
|
|
|
|
substr("foo", $i);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotFloat()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$i = rand(0, 1) ? 1 : 0.1;
|
|
|
|
Assert::assertIsNotFloat($i);
|
|
|
|
substr("foo", $i);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotInt()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$a = rand(0, 1) ? 1 : [1];
|
|
|
|
Assert::assertIsNotInt($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotNumeric()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @return numeric|array */
|
|
|
|
function f() { return rand(0,1) ? 1 : [1]; }
|
|
|
|
$a = f();
|
|
|
|
Assert::assertIsNotNumeric($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotObject()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$a = rand(0, 1) ? ((object)[]) : [1];
|
|
|
|
Assert::assertIsNotObject($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotResource()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$a = rand(0, 1) ? STDIN : [1];
|
|
|
|
Assert::assertIsNotResource($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotString()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$a = rand(0, 1) ? "foo" : [1];
|
|
|
|
Assert::assertIsNotString($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotScalar()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
$a = rand(0, 1) ? "foo" : [1];
|
|
|
|
Assert::assertIsNotScalar($a);
|
|
|
|
array_pop($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotCallable()
|
2019-02-10 11:34:51 +01:00
|
|
|
Given I have the following code
|
2019-02-10 07:19:06 +01:00
|
|
|
"""
|
2019-02-10 11:34:51 +01:00
|
|
|
/** @return callable|float */
|
|
|
|
function f() { return rand(0,1) ? 'f' : 1.1; }
|
|
|
|
$a = f();
|
2019-02-10 07:19:06 +01:00
|
|
|
Assert::assertIsNotCallable($a);
|
|
|
|
atan($a);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|
|
|
|
Scenario: Assert::assertIsNotIterable()
|
|
|
|
Given I have the following code
|
|
|
|
"""
|
|
|
|
/** @var string|iterable $s */
|
|
|
|
$s = rand(0, 1) ? "foo" : [1];
|
|
|
|
Assert::assertIsNotIterable($s);
|
|
|
|
strlen($s);
|
|
|
|
"""
|
|
|
|
When I run Psalm
|
|
|
|
Then I see no errors
|
|
|
|
|