Skip to content

0.5.0

Choose a tag to compare

@github-actions github-actions released this 23 Nov 06:17
· 10 commits to refs/heads/main since this release
094fa98

What's new since 0.4.0

DrevOps.TestingPractices.DataProviderPrefix
DrevOps.TestingPractices.DataProviderMatchesTestName
DrevOps.TestingPractices.DataProviderOrder

DrevOps.TestingPractices.DataProviderPrefix

Purpose

Enforces naming conventions for PHPUnit data provider methods. This sniff ensures that data provider methods start with a configurable prefix (default: dataProvider). It provides auto-fixing capabilities to rename methods and update all references.

Configuration

  • prefix: The required prefix for data provider methods (default: dataProvider)

Examples

✓ Valid:

class UserTest extends TestCase {
    /**
     * @dataProvider dataProviderValidCases
     */
    public function testSomething($input, $expected): void {
        $this->assertEquals($expected, $input);
    }

    public function dataProviderValidCases(): array {
        return [['input1', 'expected1']];
    }
}

✗ Invalid:

class UserTest extends TestCase {
    /**
     * @dataProvider providerInvalidCases
     */
    public function testSomething($input, $expected): void {
        $this->assertEquals($expected, $input);
    }

    // ERROR: Data provider method "providerInvalidCases" should start with 
    // prefix "dataProvider", suggested name: "dataProviderInvalidCases"
    public function providerInvalidCases(): array {
        return [['input1', 'expected1']];
    }

    /**
     * @dataProvider casesForAnotherTest
     */
    public function testAnother($value): void {
        $this->assertNotEmpty($value);
    }

    // ERROR: Data provider method "casesForAnotherTest" should start with 
    // prefix "dataProvider", suggested name: "dataProviderForAnotherTest"
    public function casesForAnotherTest(): array {
        return [['value1']];
    }

    /**
     * @dataProvider provideDataForTest
     */
    public function testWithProvide($data): void {
        $this->assertIsString($data);
    }

    // ERROR: Data provider method "provideDataForTest" should start with 
    // prefix "dataProvider", suggested name: "dataProviderDataForTest"
    public function provideDataForTest(): array {
        return [['data1']];
    }
}

DrevOps.TestingPractices.DataProviderMatchesTestName

Purpose

Enforces that data provider method names match the test method names they serve. The provider name must end with the exact test name (after removing the "test" prefix). This improves code readability and maintains a clear relationship between tests and their data providers.

Configuration

None

Examples

✓ Valid:

class UserTest extends TestCase {
    /**
     * @dataProvider dataProviderUserLogin
     */
    public function testUserLogin($user, $pass): void {
        $this->assertNotEmpty($user);
    }

    public function dataProviderUserLogin(): array {
        return [['user1', 'pass1']];
    }

    /**
     * @dataProvider providerEmailValidation
     */
    public function testEmailValidation($email): void {
        $this->assertNotEmpty($email);
    }

    // Different prefix is OK, as long as it ends with "EmailValidation"
    public function providerEmailValidation(): array {
        return [['test@example.com']];
    }

    /**
     * @dataProvider AuthenticationScenarios
     */
    public function testAuthenticationScenarios($scenario): void {
        $this->assertIsString($scenario);
    }

    // No prefix is OK, as long as it matches exactly
    public function AuthenticationScenarios(): array {
        return [['scenario1']];
    }

    #[DataProvider('dataProviderPasswordValidation')]
    public function testPasswordValidation($password): void {
        $this->assertNotEmpty($password);
    }

    // Works with PHP 8 attributes too
    public function dataProviderPasswordValidation(): array {
        return [['password123']];
    }
}

✗ Invalid:

class UserTest extends TestCase {
    /**
     * @dataProvider dataProviderLogin
     */
    public function testUserLogin($user, $pass): void {
        $this->assertNotEmpty($user);
    }

    // ERROR: Data provider method "dataProviderLogin" does not match test 
    // method "testUserLogin". Expected provider name to end with "UserLogin"
    public function dataProviderLogin(): array {
        return [['user1', 'pass1']];
    }

    /**
     * @dataProvider dataProviderEmailValidationCases
     */
    public function testEmailValidation($email): void {
        $this->assertNotEmpty($email);
    }

    // ERROR: Data provider method "dataProviderEmailValidationCases" does not 
    // match test method "testEmailValidation". Expected provider name to end 
    // with "EmailValidation"
    public function dataProviderEmailValidationCases(): array {
        return [['test@example.com']];
    }

    /**
     * @dataProvider providerAuth
     */
    public function testAuthenticationScenarios($scenario): void {
        $this->assertIsString($scenario);
    }

    // ERROR: Data provider method "providerAuth" does not match test method 
    // "testAuthenticationScenarios". Expected provider name to end with 
    // "AuthenticationScenarios"
    public function providerAuth(): array {
        return [['scenario1']];
    }

    #[DataProvider('dataProviderPass')]
    public function testPasswordValidation($password): void {
        $this->assertNotEmpty($password);
    }

    // ERROR: Data provider method "dataProviderPass" does not match test 
    // method "testPasswordValidation". Expected provider name to end with 
    // "PasswordValidation"
    public function dataProviderPass(): array {
        return [['password123']];
    }
}

DrevOps.TestingPractices.DataProviderOrder

Purpose

Enforces ordering of data provider and test methods in test files. This ensures structural organization and improves code readability. By default, data providers should be defined after their test methods. Helper methods between tests and providers are allowed.

Configuration

  • providerPosition: Expected position of data provider relative to test (default: after)
    • after: Data providers should appear after their test methods (default)
    • before: Data providers should appear before their test methods

Examples

✓ Valid (providerPosition="after"):

class UserTest extends TestCase {
    /**
     * @dataProvider dataProviderUserLogin
     */
    public function testUserLogin($user, $pass): void {
        $this->assertNotEmpty($user);
    }

    // Provider after test - CORRECT
    public function dataProviderUserLogin(): array {
        return [['user1', 'pass1']];
    }

    /**
     * @dataProvider dataProviderEmailValidation
     */
    public function testEmailValidation($email): void {
        $this->assertNotEmpty($email);
    }

    // Helper methods between test and provider are allowed
    private function helperValidate(): void {
        // Helper logic
    }

    // Provider still after test - CORRECT
    public function dataProviderEmailValidation(): array {
        return [['test@example.com']];
    }

    #[DataProvider('dataProviderAuthentication')]
    public function testAuthentication($scenario): void {
        $this->assertIsString($scenario);
    }

    // Works with PHP 8 attributes too
    public function dataProviderAuthentication(): array {
        return [['scenario1']];
    }
}

✗ Invalid (providerPosition="after"):

class UserTest extends TestCase {
    // Provider before test - WRONG ORDER
    public function dataProviderUserLogin(): array {
        return [['user1', 'pass1']];
    }

    /**
     * @dataProvider dataProviderUserLogin
     */
    // ERROR: Data provider method "dataProviderUserLogin" (line 10) appears 
    // before test method "testUserLogin" (line 17). Providers should be 
    // defined after their test methods
    public function testUserLogin($user, $pass): void {
        $this->assertNotEmpty($user);
    }

    // Another provider before test - WRONG ORDER
    public function dataProviderEmailValidation(): array {
        return [['test@example.com']];
    }

    /**
     * @dataProvider dataProviderEmailValidation
     */
    // ERROR: Data provider method "dataProviderEmailValidation" (line 24) 
    // appears before test method "testEmailValidation" (line 31). Providers 
    // should be defined after their test methods
    public function testEmailValidation($email): void {
        $this->assertNotEmpty($email);
    }
}

Note: All three rules:

  • Work with both @dataProvider annotations and PHP 8 #[DataProvider] attributes
  • Skip external providers referenced as ClassName::methodName
  • Only apply to test classes (classes ending with Test or TestCase, or extending TestCase)

Full Changelog: 0.4.0...0.5.0

@AlexSkrypnyk