Laravel Tdd

作者 affaan-mef648e01899b無授權條款275K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫3 天前更新

Desarrollo guiado por pruebas para Laravel con PHPUnit y Pest, factories, pruebas de base de datos, fakes y objetivos de cobertura.

AI 產生的概覽

指導 Laravel 的測試驅動開發,涵蓋 PHPUnit 與 Pest、factory、資料庫測試、fake 與覆蓋率目標。

功能
此技能為 Laravel 應用程式提供測試驅動開發流程,遵循紅-綠-重構循環。它說明如何選擇測試層級(單元、功能、整合)、資料庫策略(例如 RefreshDatabase),以及在 Pest 與 PHPUnit 之間選擇測試框架。內容也涵蓋 factory 與狀態、job、queue、mail、notification 和 event 的 fake、Sanctum 驗證測試、HTTP fake、授權測試、Inertia 功能測試、覆蓋率目標以及測試指令。
適用情境
適用於為 Laravel 應用程式新增功能或端點、修正錯誤或重構,以及為 Eloquent 模型、policy、job 和 notification 撰寫測試。也適合希望採用一致 TDD 方法並達到 80% 以上單元與功能覆蓋率的團隊。
執行需求
需要一個使用 PHPUnit 或 Pest 的 Laravel 專案、PHP,以及測試資料庫設定(例如記憶體中的 SQLite)。覆蓋率測量需要 pcov 或 XDEBUG_MODE=coverage。此技能僅包含說明,不附帶指令碼。

Flujo de Trabajo TDD en Laravel

Desarrollo guiado por pruebas para aplicaciones Laravel usando PHPUnit y Pest con 80%+ de cobertura (unit + feature).

Cuándo Usar

  • Nuevas funcionalidades o endpoints en Laravel
  • Correcciones de bugs o refactorizaciones
  • Probar modelos Eloquent, policies, jobs y notifications
  • Preferir Pest para pruebas nuevas a menos que el proyecto ya esté estandarizado en PHPUnit

Cómo Funciona

Ciclo Rojo-Verde-Refactorizar

  1. Escribir una prueba fallida
  2. Implementar el cambio mínimo para que pase
  3. Refactorizar manteniendo las pruebas en verde

Capas de Prueba

  • Unit: clases PHP puras, objetos de valor, servicios
  • Feature: endpoints HTTP, autenticación, validación, policies
  • Integration: base de datos + colas + límites externos

Elegir capas según el alcance:

  • Usar pruebas Unit para lógica de negocio pura y servicios.
  • Usar pruebas Feature para HTTP, autenticación, validación y forma de respuesta.
  • Usar pruebas Integration cuando se validen BD/colas/servicios externos juntos.

Estrategia de Base de Datos

  • RefreshDatabase para la mayoría de pruebas feature/integration (ejecuta migraciones una vez por ejecución de prueba, luego envuelve cada prueba en una transacción cuando está soportado; las bases de datos en memoria pueden re-migrar por prueba)
  • DatabaseTransactions cuando el esquema ya está migrado y solo se necesita rollback por prueba
  • DatabaseMigrations cuando se necesita un migrate/fresh completo para cada prueba y se puede asumir el costo

Usar RefreshDatabase como predeterminado para pruebas que tocan la base de datos: para bases de datos con soporte de transacciones, ejecuta las migraciones una vez por ejecución de prueba (mediante un flag estático) y envuelve cada prueba en una transacción; para SQLite :memory: o conexiones sin transacciones, migra antes de cada prueba. Usar DatabaseTransactions cuando el esquema ya está migrado y solo se necesitan rollbacks por prueba.

Elección del Framework de Pruebas

  • Usar Pest por defecto para pruebas nuevas cuando esté disponible.
  • Usar PHPUnit solo si el proyecto ya lo estandariza o requiere herramientas específicas de PHPUnit.

Ejemplos

Ejemplo con PHPUnit

php
use App\Models\User;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase;
final class ProjectControllerTest extends TestCase{    use RefreshDatabase;
    public function test_owner_can_create_project(): void    {        $user = User::factory()->create();
        $response = $this->actingAs($user)->postJson('/api/projects', [            'name' => 'New Project',        ]);
        $response->assertCreated();        $this->assertDatabaseHas('projects', ['name' => 'New Project']);    }}

Ejemplo de Prueba Feature (Capa HTTP)

php
use App\Models\Project;use App\Models\User;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase;
final class ProjectIndexTest extends TestCase{    use RefreshDatabase;
    public function test_projects_index_returns_paginated_results(): void    {        $user = User::factory()->create();        Project::factory()->count(3)->for($user)->create();
        $response = $this->actingAs($user)->getJson('/api/projects');
        $response->assertOk();        $response->assertJsonStructure(['success', 'data', 'error', 'meta']);    }}

Ejemplo con Pest

php
use App\Models\User;use Illuminate\Foundation\Testing\RefreshDatabase;
use function Pest\Laravel\actingAs;use function Pest\Laravel\assertDatabaseHas;
uses(RefreshDatabase::class);
test('owner can create project', function () {    $user = User::factory()->create();
    $response = actingAs($user)->postJson('/api/projects', [        'name' => 'New Project',    ]);
    $response->assertCreated();    assertDatabaseHas('projects', ['name' => 'New Project']);});

Ejemplo de Prueba Feature con Pest (Capa HTTP)

php
use App\Models\Project;use App\Models\User;use Illuminate\Foundation\Testing\RefreshDatabase;
use function Pest\Laravel\actingAs;
uses(RefreshDatabase::class);
test('projects index returns paginated results', function () {    $user = User::factory()->create();    Project::factory()->count(3)->for($user)->create();
    $response = actingAs($user)->getJson('/api/projects');
    $response->assertOk();    $response->assertJsonStructure(['success', 'data', 'error', 'meta']);});

Factories y Estados

  • Usar factories para datos de prueba
  • Definir estados para casos límite (archivado, admin, trial)
php
$user = User::factory()->state(['role' => 'admin'])->create();

Pruebas de Base de Datos

  • Usar RefreshDatabase para estado limpio
  • Mantener las pruebas aisladas y deterministas
  • Preferir assertDatabaseHas sobre consultas manuales

Ejemplo de Prueba de Persistencia

php
use App\Models\Project;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase;
final class ProjectRepositoryTest extends TestCase{    use RefreshDatabase;
    public function test_project_can_be_retrieved_by_slug(): void    {        $project = Project::factory()->create(['slug' => 'alpha']);
        $found = Project::query()->where('slug', 'alpha')->firstOrFail();
        $this->assertSame($project->id, $found->id);    }}

Fakes para Efectos Secundarios

  • Bus::fake() para jobs
  • Queue::fake() para trabajo en cola
  • Mail::fake() y Notification::fake() para notificaciones
  • Event::fake() para eventos de dominio
php
use Illuminate\Support\Facades\Queue;
Queue::fake();
dispatch(new SendOrderConfirmation($order->id));
Queue::assertPushed(SendOrderConfirmation::class);
php
use Illuminate\Support\Facades\Notification;
Notification::fake();
$user->notify(new InvoiceReady($invoice));
Notification::assertSentTo($user, InvoiceReady::class);

Pruebas de Autenticación (Sanctum)

php
use Laravel\Sanctum\Sanctum;
Sanctum::actingAs($user);
$response = $this->getJson('/api/projects');$response->assertOk();

HTTP y Servicios Externos

  • Usar Http::fake() para aislar APIs externas
  • Verificar payloads salientes con Http::assertSent()

Objetivos de Cobertura

  • Aplicar 80%+ de cobertura para pruebas unit + feature
  • Usar pcov o XDEBUG_MODE=coverage en CI

Comandos de Prueba

  • php artisan test
  • vendor/bin/phpunit
  • vendor/bin/pest

Configuración de Pruebas

  • Usar phpunit.xml para establecer DB_CONNECTION=sqlite y DB_DATABASE=:memory: para pruebas rápidas
  • Mantener un entorno separado para pruebas para evitar tocar datos de desarrollo/producción

Pruebas de Autorización

php
use Illuminate\Support\Facades\Gate;
$this->assertTrue(Gate::forUser($user)->allows('update', $project));$this->assertFalse(Gate::forUser($otherUser)->allows('update', $project));

Pruebas Feature con Inertia

Al usar Inertia.js, verificar el nombre del componente y las props con los helpers de testing de Inertia.

php
use App\Models\User;use Inertia\Testing\AssertableInertia;use Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase;
final class DashboardInertiaTest extends TestCase{    use RefreshDatabase;
    public function test_dashboard_inertia_props(): void    {        $user = User::factory()->create();
        $response = $this->actingAs($user)->get('/dashboard');
        $response->assertOk();        $response->assertInertia(fn (AssertableInertia $page) => $page            ->component('Dashboard')            ->where('user.id', $user->id)            ->has('projects')        );    }}

Preferir assertInertia sobre aserciones JSON crudas para mantener las pruebas alineadas con las respuestas de Inertia.

來源與署名

來源:affaan-m/ecc位於docs/es/skills/laravel-tdd提交ef648e0

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架