laravel-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLaravel 13 Testing — Pest PHP 4 & PHPUnit 12
Laravel 13 测试 — Pest PHP 4 & PHPUnit 12
Supports both Pest PHP 4 and PHPUnit 12. See Framework Detection below.PHPUnit version note: Laravel 13 ships within its defaultphpunit/phpunit: ^12.5.12. All patterns in this skill are compatible with PHPUnit 11, 12, and 13.composer.json
Comprehensive testing guide for Laravel 13 applications. Contains 24 rules across 6 categories for writing fast, readable, and reliable tests. Supports both Pest PHP 4 and PHPUnit 12 (Laravel 13 default).
同时支持Pest PHP 4和PHPUnit 12。 详见下方的框架检测部分。PHPUnit版本说明: Laravel 13在默认的中附带composer.json。本技能中的所有规则均兼容PHPUnit 11、12和13版本。phpunit/phpunit: ^12.5.12
Laravel 13应用的全面测试指南。包含6个分类下的24条规则,用于编写快速、易读且可靠的测试。同时支持Pest PHP 4和PHPUnit 12(Laravel 13默认测试框架)。
Framework Detection
框架检测
Before writing or reviewing any test code, detect which testing framework the project uses:
在编写或评审任何测试代码之前,请先检测项目使用的测试框架:
Step 1 — Check composer.json
步骤1 — 检查composer.json
bash
undefinedbash
undefinedLook for these in require-dev:
在require-dev中查找以下内容:
"pestphp/pest" → Pest
"pestphp/pest" → 使用Pest
"phpunit/phpunit" (without pest) → PHPUnit
"phpunit/phpunit"(无pest依赖)→ 使用PHPUnit
- If `pestphp/pest` is present → **use Pest syntax**
- If only `phpunit/phpunit` is present → **use PHPUnit syntax**
- If both are present → **Pest takes priority** (Pest runs on top of PHPUnit)
- 若存在`pestphp/pest` → **使用Pest语法**
- 若仅存在`phpunit/phpunit` → **使用PHPUnit语法**
- 若两者都存在 → **优先使用Pest**(Pest基于PHPUnit运行)Step 2 — Check for tests/Pest.php
步骤2 — 检查是否存在tests/Pest.php
- If exists → Pest is configured, use Pest syntax
tests/Pest.php
- 若文件存在 → 已配置Pest,使用Pest语法
tests/Pest.php
Step 3 — If still unclear, ask the user
步骤3 — 若仍不明确,询问用户
"I couldn't detect the testing framework. Does this project use Pest PHP or PHPUnit?"
"我无法检测到测试框架。该项目使用Pest PHP还是PHPUnit?"
Syntax Reference
语法参考
Test Declaration
测试声明
| Pest | PHPUnit | |
|---|---|---|
| Test function | | |
| Readable name | | |
| Grouping | | Test class name / nested classes |
| Trait application | | |
| Before each | | |
| After each | | |
| Parameterised | | |
| Global setup | | Base |
| Pest | PHPUnit | |
|---|---|---|
| 测试函数 | | |
| 可读命名 | | |
| 分组 | | 测试类名称 / 嵌套类 |
| Trait应用 | | 在类内部使用 |
| 每次测试前执行 | | |
| 每次测试后执行 | | |
| 参数化测试 | | |
| 全局设置 | 在 | 基础 |
Core assertions (identical in both frameworks)
核心断言(两个框架中完全一致)
assertStatusassertJsonassertJsonPathassertDatabaseHasassertModelExistsactingAsMail::fake()Queue::fake()Event::fake()Notification::fake()Storage::fake()assertStatusassertJsonassertJsonPathassertDatabaseHasassertModelExistsactingAsMail::fake()Queue::fake()Event::fake()Notification::fake()Storage::fake()When to Apply
适用场景
Reference these guidelines when:
- Writing feature or unit tests for Laravel
- Testing HTTP endpoints and API responses
- Creating factories and test data
- Asserting database state after operations
- Faking Mail, Queue, Notification, or Event facades
- Testing authenticated routes and API tokens
- Organising tests with describe blocks, datasets, or test classes
在以下场景中参考本指南:
- 为Laravel编写功能测试或单元测试
- 测试HTTP端点和API响应
- 创建工厂和测试数据
- 验证操作后的数据库状态
- 模拟Mail、Queue、Notification或Event Facade
- 测试认证路由和API令牌
- 使用describe块、数据集或测试类组织测试
Rule Categories by Priority
按优先级划分的规则分类
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | HTTP & Feature Tests | CRITICAL | |
| 2 | Model Factories | CRITICAL | |
| 3 | Database Assertions | HIGH | |
| 4 | Faking Services | HIGH | |
| 5 | Authentication Testing | HIGH | |
| 6 | Test Organisation Patterns | MEDIUM | |
| 优先级 | 分类 | 影响程度 | 前缀 |
|---|---|---|---|
| 1 | HTTP & 功能测试 | 关键 | |
| 2 | 模型工厂 | 关键 | |
| 3 | 数据库断言 | 高 | |
| 4 | 服务模拟 | 高 | |
| 5 | 认证测试 | 高 | |
| 6 | 测试组织模式 | 中 | |
Quick Reference
快速参考
1. HTTP & Feature Tests (CRITICAL)
1. HTTP & 功能测试(关键)
- - Arrange/Act/Assert with factories — Pest + PHPUnit examples
http-test-structure - - assertStatus, assertJson, assertRedirect, assertJsonMissing
http-assert-response - - Fluent assertJson with AssertableJson closure
http-assert-json-fluent - - RefreshDatabase vs DatabaseTransactions — when to use each
http-refresh-database
- - 结合工厂使用Arrange/Act/Assert模式 — 含Pest + PHPUnit示例
http-test-structure - - assertStatus、assertJson、assertRedirect、assertJsonMissing
http-assert-response - - 使用AssertableJson闭包的流畅式assertJson
http-assert-json-fluent - - RefreshDatabase与DatabaseTransactions的对比 — 何时使用各自
http-refresh-database
2. Model Factories (CRITICAL)
2. 模型工厂(关键)
- - Define factories with typed fake data and PHP 8.3 syntax
factory-define - - Factory states for distinct test scenarios
factory-states - - sequence() for varied data across multiple records
factory-sequences - - has(), for(), recycle(), afterCreating()
factory-relationships
- - 使用类型化假数据和PHP 8.3语法定义工厂
factory-define - - 用于不同测试场景的工厂状态
factory-states - - 使用sequence()生成多条不同数据记录
factory-sequences - - has()、for()、recycle()、afterCreating()
factory-relationships
3. Database Assertions (HIGH)
3. 数据库断言(高)
- - assertDatabaseHas, assertModelExists for presence checks
db-assert-has - - assertDatabaseMissing, assertModelMissing for deletion
db-assert-missing - - assertSoftDeleted, trashed() factory state
db-assert-soft-deletes
- - 使用assertDatabaseHas、assertModelExists检查存在性
db-assert-has - - 使用assertDatabaseMissing、assertModelMissing检查删除
db-assert-missing - - assertSoftDeleted、trashed()工厂状态
db-assert-soft-deletes
4. Faking Services (HIGH)
4. 服务模拟(高)
- - Mail::fake(), assertSent vs assertQueued, assertNothingSent
fake-mail - - Queue::fake(), assertPushed, assertPushedOn
fake-queue - - Notification::fake(), assertSentTo, assertCount
fake-notification - - Event::fake(), assertDispatched, assertNotDispatched
fake-event - - Storage::fake(), UploadedFile::fake(), assertExists
fake-storage - - Agent::fake(), assertPrompted, preventStrayPrompts (Laravel 13+)
fake-ai-agent - - Image::fake(), Audio::fake(), Transcription::fake() (Laravel 13+)
fake-ai-media - - Embeddings::fake(), Reranking::fake(), Files::fake(), Stores::fake() (Laravel 13+)
fake-ai-data
- - Mail::fake()、assertSent与assertQueued对比、assertNothingSent
fake-mail - - Queue::fake()、assertPushed、assertPushedOn
fake-queue - - Notification::fake()、assertSentTo、assertCount
fake-notification - - Event::fake()、assertDispatched、assertNotDispatched
fake-event - - Storage::fake()、UploadedFile::fake()、assertExists
fake-storage - - Agent::fake()、assertPrompted、preventStrayPrompts(Laravel 13+)
fake-ai-agent - - Image::fake()、Audio::fake()、Transcription::fake()(Laravel 13+)
fake-ai-media - - Embeddings::fake()、Reranking::fake()、Files::fake()、Stores::fake()(Laravel 13+)
fake-ai-data
5. Authentication Testing (HIGH)
5. 认证测试(高)
- - actingAs() for session/web authenticated tests
auth-acting-as - - Sanctum::actingAs() for API token authentication
auth-sanctum
- - 使用actingAs()进行会话/网页认证测试
auth-acting-as - - 使用Sanctum::actingAs()进行API令牌认证
auth-sanctum
6. Test Organisation Patterns (MEDIUM)
6. 测试组织模式(中)
- - describe()/it() (Pest) or test class organisation (PHPUnit)
pest-describe-it - - with() datasets (Pest) or #[DataProvider] (PHPUnit)
pest-datasets - - beforeEach/afterEach (Pest) or setUp/tearDown (PHPUnit)
pest-hooks
- - describe()/it()(Pest)或测试类组织(PHPUnit)
pest-describe-it - - with()数据集(Pest)或#[DataProvider](PHPUnit)
pest-datasets - - beforeEach/afterEach(Pest)或setUp/tearDown(PHPUnit)
pest-hooks
Essential Patterns
核心示例
Pest
Pest
php
<?php
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('authenticated user can create a post', function () {
$user = User::factory()->create();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Hello World', 'body' => 'Content.'])
->assertStatus(201)
->assertJsonPath('data.title', 'Hello World');
$this->assertDatabaseHas('posts', ['title' => 'Hello World', 'user_id' => $user->id]);
});php
<?php
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('authenticated user can create a post', function () {
$user = User::factory()->create();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Hello World', 'body' => 'Content.'])
->assertStatus(201)
->assertJsonPath('data.title', 'Hello World');
$this->assertDatabaseHas('posts', ['title' => 'Hello World', 'user_id' => $user->id]);
});PHPUnit
PHPUnit
php
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostControllerTest extends TestCase
{
use RefreshDatabase;
public function test_authenticated_user_can_create_a_post(): void
{
$user = User::factory()->create();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Hello World', 'body' => 'Content.'])
->assertStatus(201)
->assertJsonPath('data.title', 'Hello World');
$this->assertDatabaseHas('posts', ['title' => 'Hello World', 'user_id' => $user->id]);
}
}php
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostControllerTest extends TestCase
{
use RefreshDatabase;
public function test_authenticated_user_can_create_a_post(): void
{
$user = User::factory()->create();
$this->actingAs($user)
->postJson('/api/posts', ['title' => 'Hello World', 'body' => 'Content.'])
->assertStatus(201)
->assertJsonPath('data.title', 'Hello World');
$this->assertDatabaseHas('posts', ['title' => 'Hello World', 'user_id' => $user->id]);
}
}How to Use
使用方法
Read individual rule files for detailed explanations and code examples.
Each rule file contains:
- YAML frontmatter with metadata (title, impact, tags)
- Brief explanation of why it matters
- Bad Example with explanation
- Good Example with both Pest and PHPUnit where syntax differs
- Laravel 13 specific context and references
阅读单个规则文件以获取详细说明和代码示例。
每个规则文件包含:
- 带有元数据(标题、影响程度、标签)的YAML前置内容
- 简要说明该规则的重要性
- 错误示例及解释
- 正确示例(若语法不同,同时提供Pest和PHPUnit版本)
- Laravel 13特定上下文和参考资料
Full Compiled Document
完整编译文档
For the complete guide with all rules expanded:
AGENTS.md如需包含所有扩展规则的完整指南,请查看:
AGENTS.md