PhpUnitTests
info on by default quick-fixGroup: PHPUnit · PhpStorm name: PhpUnitTestsInspection
A grab-bag of PHPUnit hygiene checks. On test method docblocks it validates the targets of @covers, @depends and @dataProvider, flags a redundant @test and (optionally) unnamed datasets. On assertion and mock-builder calls it points at generic assertions that have a dedicated, more expressive PHPUnit counterpart (assertTrue(!$x) → assertNotTrue($x), assertSame(1, count($l)) → assertCount(1, $l), ->will($this->returnValue(…)) → ->willReturn(…), …) and rewrites them.
The rule has two independent halves:
- Part A — docblock tags on methods (D1–D12).
- Part B — method calls whose name starts with
assert, or isexpectsorwill(D13–D30).
Neither half checks that the class extends a PHPUnit test case: every method of every class-like and every matching method call is examined.
Example
Docblock checks (SUGGEST_TO_USE_NAMED_DATASETS on):
<?php
namespace Shop\Billing {
class Ledger extends \SplObjectStorage {
public function settle() {}
}
}
namespace {
use Shop\Billing\Ledger as Book;
class LedgerTest {
/** @covers Book::settle */
public function testSettles() {}
/** @covers Book::attach() */
public function testAttachesInherited() {}
/**
* Rolls back.
* @covers Book::rollback
*/
public function testRollback() {}
/** @covers \Shop\Billing\Journal */
public function testJournal() {}
/** @covers ::strlen */
public function testMeasures() {}
/** @covers Book::<protected> */
public function testInternals() {}
/** Unlike @covers Nowhere, this is prose. */
public function audit_notes() {}
/** @test */
public function seedsLedger() {}
/** @test */
public function testBalances() {}
/** @depends seedsLedger */
public function testAfterSeed() {}
/** @depends testBalances */
public function testAfterBalance() {}
/** @depends helper */
public function testNeedsHelper() {}
/** @depends \LedgerTest::vanished */
public function testNeedsVanished() {}
/** @dataProvider amounts */
public function testAmounts($v) {}
/** @dataProvider plainAmounts */
public function testPlainAmounts($v) {}
/** @dataProvider noAmounts */
public function testNoAmounts($v) {}
/** @dataProvider phantom */
public function testPhantom($v) {}
public function helper() {}
public static function amounts() { return ['ten' => [10], 'zero' => [0]]; }
public static function plainAmounts() { return [[10], [0]]; }
public static function noAmounts() { return array(); }
}
}Reported:
- line 22: The @covers target 'Book::rollback' cannot be resolved.
- line 25: The @covers target '\Shop\Billing\Journal' cannot be resolved.
- line 39: Remove '@test': the method name already marks it as a test.
- line 49: The @depends target is missing or is not a test.
- line 52: The @depends target is missing or is not a test.
- line 58: Give the provider's datasets string keys.
- line 64: The @dataProvider target cannot be resolved to a method.
Options
| Option | Type | Default | Effect |
|---|---|---|---|
PHP_UNIT_VERSION | enum | PHPUNIT80 | Target PHPUnit version, one of PHPUNIT70, PHPUNIT71, PHPUNIT72, PHPUNIT73, PHPUNIT74, PHPUNIT75, PHPUNIT80, PHPUNIT81, PHPUNIT82, PHPUNIT83, PHPUNIT84, PHPUNIT85, PHPUNIT90, PHPUNIT91, PHPUNIT92, PHPUNIT93, PHPUNIT94, PHPUNIT95 (ordered; comparisons are by this order). Below 8.0 D20 suggests assertInternalType/assertNotInternalType, from 8.0 assertIs*/assertIsNot*. D25 only runs below 9.0. D23 uses the NotExists negative names below 9.1 and DoesNotExist from 9.1. D26/D27 use assertRegExp/assertNotRegExp below 9.1 and assertMatchesRegularExpression/assertDoesNotMatchRegularExpression from 9.1. No other effect on detection or fixes. Conformance passes it as PhpUnitVersion.PHPUNIT75 style values; strip the prefix. Unset → inferred from the indexed PHPUnit (see Divergences), else PHPUNIT80. |
SUGGEST_TO_USE_ASSERTSAME | bool | false | Enables D17. |
SUGGEST_TO_USE_NAMED_DATASETS | bool | false | Enables D6. |
PROMOTE_PHPUNIT_API | bool | true | Enables D18–D28. |
PROMOTE_MOCKING_ONCE | bool | true | Enables D29. |
PROMOTE_MOCKING_WILL_RETURN | bool | true | Enables D30. |
Configure
In custos.json:
{
"rules": {
"PhpUnitTests": {
"enabled": false,
"options": {
"PHP_UNIT_VERSION": "PHPUNIT80",
"SUGGEST_TO_USE_ASSERTSAME": false,
"SUGGEST_TO_USE_NAMED_DATASETS": false,
"PROMOTE_PHPUNIT_API": true,
"PROMOTE_MOCKING_ONCE": true,
"PROMOTE_MOCKING_WILL_RETURN": true
}
}
}
}Suppress
Before the statement or declaration (or the first statement of the file), either of:
// @custos-ignore PhpUnitTests
/**
* @noinspection PhpUnitTestsInspection
*/