mcpField
P
php-testing

php-testing

github.com/pluginagentmarketplace测试与质量442 次安装42 周前更新
代码仓库

关于 php-testing

php-testing 是面向 PHP 开发者的测试学习技能,内容涵盖从基础测试到 CI/CD,并按主题和水平组织 PHPUnit、Pest 与 Mockery 指南及示例。

主要功能

  1. 01PHPUnit 11 基础
  2. 02Pest 3 测试模式
  3. 03使用 Mockery 和 Prophecy 模拟
  4. 04TDD 与集成测试
  5. 05CI/CD 指南与示例

适用场景

  1. 01学习 PHPUnit 测试结构与断言
  2. 02选择模拟对象、桩或间谍
  3. 03测试数据库和 API 集成
  4. 04排查 CI 中失败的测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pluginagentmarketplace/custom-plugin-php --skill php-testing

安装后在 Claude Code 中输入/php-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
config.yaml
schema.json
references/
GUIDE.md
PATTERNS.md
scripts/
validate.py

详细介绍

PHP 测试技能

掌握 PHP 测试策略的原子技能

概述

全面的 PHP 测试技能,涵盖 PHPUnit 11、Pest 3、TDD 方法论、模拟策略和 CI/CD 集成。

技能参数

输入验证
interface SkillParams {
  topic:
    | "phpunit"          // PHPUnit framework
    | "pest"             // Pest framework
    | "mocking"          // Mockery, Prophecy
    | "tdd"              // Test-driven development
    | "integration"      // Database, API testing
    | "ci-cd";           // GitHub Actions, GitLab CI

  level: "beginner" | "intermediate" | "advanced";
  framework?: "laravel" | "symfony" | "none";
  coverage_goal?: number;
}
验证规则
validation:
  topic:
    required: true
    allowed: [phpunit, pest, mocking, tdd, integration, ci-cd]
  level:
    required: true
  framework:
    default: "none"

学习模块

模块 1:PHPUnit 基础知识
beginner:
  - Test case structure
  - Basic assertions
  - Running tests

intermediate:
  - Data providers
  - Fixtures (setUp/tearDown)
  - Test doubles

advanced:
  - Attributes (#[Test], #[DataProvider])
  - Code coverage
  - Parallel execution
模块 2:Pest 框架
beginner:
  - Expectations syntax
  - Test organization
  - Groups and filtering

intermediate:
  - Higher-order tests
  - Datasets
  - Hooks

advanced:
  - Mutation testing (--mutate)
  - Architecture testing
  - Custom expectations
模块 3:模拟策略
beginner:
  - Mock basics
  - Stubs vs mocks
  - Simple expectations

intermediate:
  - Partial mocks
  - Spies
  - Argument matching

advanced:
  - Mock chains
  - Return callbacks
  - Exception testing

错误处理与重试逻辑

errors:
  TEST_FAILURE:
    code: "TEST_001"
    recovery: "Compare expected vs actual, check setup"

  MOCK_ERROR:
    code: "TEST_002"
    recovery: "Verify mock expectations and injection"

  FLAKY_TEST:
    code: "TEST_003"
    recovery: "Check isolation, fix race conditions"

retry:
  max_attempts: 2
  backoff:
    type: linear
    delay_ms: 100

代码示例

PHPUnit 测试(PHP 8.2+)
<?php
declare(strict_types=1);

namespace Tests\Unit;

use App\Services\Calculator;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\DataProvider;

final class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        $this->calculator = new Calculator();
    }

    #[Test]
    public function it_adds_two_numbers(): void
    {
        $result = $this->calculator->add(2, 3);

        $this->assertSame(5, $result);
    }

    #[Test]
    #[DataProvider('divisionProvider')]
    public function it_divides_correctly(int $a, int $b, float $expected): void
    {
        $result = $this->calculator->divide($a, $b);

        $this->assertEqualsWithDelta($expected, $result, 0.0001);
    }

    public static function divisionProvider(): array
    {
        return [
            'whole' => [10, 2, 5.0],
            'decimal' => [7, 2, 3.5],
        ];
    }

    #[Test]
    public function it_throws_on_division_by_zero(): void
    {
        $this->expectException(\DivisionByZeroError::class);

        $this->calculator->divide(10, 0);
    }
}
Pest 测试
<?php
use App\Models\User;
use function Pest\Laravel\{actingAs, post, assertDatabaseHas};

describe('User Registration', function () {
    it('allows new user registration', function () {
        post('/register', [
            'name' => 'John',
            'email' => '[email protected]',
            'password' => 'password',
            'password_confirmation' => 'password',
        ])
        ->assertRedirect('/dashboard');

        assertDatabaseHas('users', ['email' => '[email protected]']);
    });

    it('requires valid email', function () {
        post('/register', ['email' => 'invalid'])
            ->assertSessionHasErrors('email');
    });
})->group('auth');
使用 Mockery 进行模拟
<?php
declare(strict_types=1);

namespace Tests\Unit;

use App\Services\UserService;
use App\Repositories\UserRepository;
use Mockery;
use PHPUnit\Framework\TestCase;

final class UserServiceTest extends TestCase
{
    public function test_creates_user(): void
    {
        // Arrange
        $repository = Mockery::mock(UserRepository::class);
        $repository
            ->shouldReceive('create')
            ->once()
            ->with(['name' => 'John', 'email' => '[email protected]'])
            ->andReturn(new User(['id' => 1]));

        $service = new UserService($repository);

        // Act
        $user = $service->createUser([
            'name' => 'John',
            'email' => '[email protected]',
        ]);

        // Assert
        $this->assertEquals(1, $user->id);
    }

    protected function tearDown(): void
    {
        Mockery::close();
    }
}
CI/CD 配置(GitHub Actions)
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          coverage: xdebug

      - name: Install dependencies
        run: composer install --no-progress

      - name: Run tests
        run: vendor/bin/phpunit --coverage-clover coverage.xml

      - name: Upload coverage
        uses: codecov/codecov-action@v3

故障排除

问题原因解决方案
测试在本地通过,在 CI 中失败环境差异检查 PHP 版本、数据库状态
未调用模拟对象未注入验证 DI,不要在类内部实例化
数据库污染状态共享使用 RefreshDatabase trait
测试缓慢数据库操作过多使用模拟对象,并行运行

质量指标

指标目标
代码覆盖率≥80%
测试速度完整测试套件 <5 分钟
不稳定率0%
测试隔离度100%

用法

Skill("php-testing", {topic: "mocking", level: "intermediate"})

评论

支持 Markdown