Skip to content

PhpUnitTests ​

info on by default quick-fix

Group: 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 is expects or will (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
<?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 ​

OptionTypeDefaultEffect
PHP_UNIT_VERSIONenumPHPUNIT80Target 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_ASSERTSAMEboolfalseEnables D17.
SUGGEST_TO_USE_NAMED_DATASETSboolfalseEnables D6.
PROMOTE_PHPUNIT_APIbooltrueEnables D18–D28.
PROMOTE_MOCKING_ONCEbooltrueEnables D29.
PROMOTE_MOCKING_WILL_RETURNbooltrueEnables D30.

Configure ​

In custos.json:

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:

php
// @custos-ignore PhpUnitTests

/**
 * @noinspection PhpUnitTestsInspection
 */

Released under the MIT License. Rule catalogue modelled on Php Inspections (EA Extended); independent clean-room implementation.