laravel-tdd

Test-driven development for Laravel with PHPUnit and Pest, factories, database testing, fakes, and coverage targets.

144,923 stars
Complexity: easy

About this skill

This skill guides the AI agent in performing Test-Driven Development for Laravel projects, ensuring robust, maintainable, and well-tested code. It outlines the 'Red-Green-Refactor' workflow, starting with writing a failing test, implementing minimal code to make it pass, and then refactoring while maintaining test success. The skill emphasizes testing various components like Eloquent models, policies, jobs, and notifications across unit and feature test layers. It supports both PHPUnit and Pest, providing guidelines on when to prefer each, along with advanced testing techniques such as factories for efficient test data generation, comprehensive database testing, and faking dependencies for isolation, all while targeting an 80%+ test coverage.

Best use case

Developing new features or API endpoints in Laravel, fixing bugs or performing refactorings, and systematically testing Eloquent models, policies, jobs, and notifications to ensure their correct behavior.

Test-driven development for Laravel with PHPUnit and Pest, factories, database testing, fakes, and coverage targets.

High-quality, well-tested Laravel code with documented tests for features, models, and business logic. The outcome includes reduced bugs, improved maintainability, and confidence in code changes due to comprehensive test coverage (typically 80% or higher), adhering to TDD best practices.

Practical example

Example input

I need to add a new 'Order Fulfillment' feature to my Laravel application. Please follow TDD principles, generate appropriate unit and feature tests using Pest, and ensure high test coverage for the new functionality. Focus on the `Order` model, associated policies, and a new `FulfillOrderJob`.

Example output

Understood. I will begin by outlining the desired behavior for the 'Order Fulfillment' feature. Then, I will write a failing feature test to cover the main flow, including test data generation via factories for `Order` and `User` models, and asserting the state changes after fulfillment. Following this, I will implement a failing unit test for the `FulfillOrderJob` and its associated logic, then write the minimal code to pass it. Next, I will address any relevant policies with failing tests, implementing code to pass them. Finally, I will refactor all new code while ensuring all tests remain green, targeting 80%+ coverage for all new components. Starting with `tests/Feature/OrderFulfillmentTest.php` and `tests/Unit/Jobs/FulfillOrderJobTest.php`...

When to use this skill

  • When building new functionalities for Laravel applications, addressing bugs, refactoring existing code, or whenever a structured, test-first approach is desired to ensure code quality and stability. It's particularly useful when aiming for high test coverage (80%+ unit and feature tests) and for new tests, preferring Pest if the project is not already standardized on PHPUnit.

When not to use this skill

  • Not suitable for extremely trivial scripts where the overhead of TDD outweighs the benefits, or in legacy projects with severe technical debt where immediate, large-scale TDD adoption might be impractical without prior refactoring efforts. In such cases, a more gradual approach to testing might be needed before full TDD can be applied.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/laravel-tdd/SKILL.md --create-dirs "https://raw.githubusercontent.com/affaan-m/everything-claude-code/main/docs/tr/skills/laravel-tdd/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/laravel-tdd/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How laravel-tdd Compares

Feature / Agentlaravel-tddStandard Approach
Platform SupportClaudeLimited / Varies
Context Awareness High Baseline
Installation ComplexityeasyN/A

Frequently Asked Questions

What does this skill do?

Test-driven development for Laravel with PHPUnit and Pest, factories, database testing, fakes, and coverage targets.

Which AI agents support this skill?

This skill is designed for Claude.

How difficult is it to install?

The installation complexity is rated as easy. You can find the installation instructions above.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Laravel TDD İş Akışı

80%+ kapsam (unit + feature) ile Laravel uygulamaları için test-driven development.

## Ne Zaman Kullanılır

- Laravel'de yeni özellikler veya endpoint'ler
- Bug düzeltmeleri veya refactoring'ler
- Eloquent model'leri, policy'leri, job'ları ve notification'ları test etme
- Proje zaten PHPUnit'te standartlaşmamışsa yeni testler için Pest'i tercih edin

## Nasıl Çalışır

### Red-Green-Refactor Döngüsü

1) Başarısız bir test yazın
2) Geçmek için minimal değişiklik uygulayın
3) Testleri yeşil tutarken refactor edin

### Test Katmanları

- **Unit**: saf PHP sınıfları, value object'leri, servisler
- **Feature**: HTTP endpoint'leri, auth, validation, policy'ler
- **Integration**: database + kuyruk + harici sınırlar

Kapsama göre katmanları seçin:

- Saf iş mantığı ve servisler için **Unit** testleri kullanın.
- HTTP, auth, validation ve yanıt şekli için **Feature** testleri kullanın.
- DB/kuyruklar/harici servisleri birlikte doğrularken **Integration** testleri kullanın.

### Database Stratejisi

- Çoğu feature/integration testi için `RefreshDatabase` (test run'ı başına bir kez migration'ları çalıştırır, ardından desteklendiğinde her testi bir transaction'a sarar; in-memory veritabanları test başına yeniden migrate edebilir)
- Şema zaten migrate edilmişse ve sadece test başına rollback'e ihtiyacınız varsa `DatabaseTransactions`
- Her test için tam bir migrate/fresh'e ihtiyacınız varsa ve maliyetini karşılayabiliyorsanız `DatabaseMigrations`

Veritabanına dokunan testler için varsayılan olarak `RefreshDatabase` kullanın: transaction desteği olan veritabanları için, test run'ı başına bir kez (static bir bayrak aracılığıyla) migration'ları çalıştırır ve her testi bir transaction'a sarar; `:memory:` SQLite veya transaction'sız bağlantılar için her testten önce migrate eder. Şema zaten migrate edilmişse ve sadece test başına rollback'lere ihtiyacınız varsa `DatabaseTransactions` kullanın.

### Test Framework Seçimi

- Mevcut olduğunda yeni testler için varsayılan olarak **Pest** kullanın.
- Proje zaten PHPUnit'te standartlaşmışsa veya PHPUnit'e özgü araçlar gerektiriyorsa sadece **PHPUnit** kullanın.

## Örnekler

### PHPUnit Örneği

```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']);
    }
}
```

### Feature Test Örneği (HTTP Katmanı)

```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']);
    }
}
```

### Pest Örneği

```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']);
});
```

### Feature Test Pest Örneği (HTTP Katmanı)

```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']);
});
```

### Factory'ler ve State'ler

- Test verileri için factory'leri kullanın
- Uç durumlar için state'leri tanımlayın (archived, admin, trial)

```php
$user = User::factory()->state(['role' => 'admin'])->create();
```

### Database Testi

- Temiz durum için `RefreshDatabase` kullanın
- Testleri izole ve deterministik tutun
- Manuel sorgular yerine `assertDatabaseHas` tercih edin

### Persistence Test Örneği

```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);
    }
}
```

### Yan Etkiler için Fake'ler

- Job'lar için `Bus::fake()`
- Kuyruğa alınmış işler için `Queue::fake()`
- Bildirimler için `Mail::fake()` ve `Notification::fake()`
- Domain event'leri için `Event::fake()`

```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);
```

### Auth Testi (Sanctum)

```php
use Laravel\Sanctum\Sanctum;

Sanctum::actingAs($user);

$response = $this->getJson('/api/projects');
$response->assertOk();
```

### HTTP ve Harici Servisler

- Harici API'leri izole etmek için `Http::fake()` kullanın
- Giden payload'ları `Http::assertSent()` ile doğrulayın

### Kapsam Hedefleri

- Unit + feature testleri için 80%+ kapsam zorlayın
- CI'da `pcov` veya `XDEBUG_MODE=coverage` kullanın

### Test Komutları

- `php artisan test`
- `vendor/bin/phpunit`
- `vendor/bin/pest`

### Test Yapılandırması

- Hızlı testler için `phpunit.xml`'de `DB_CONNECTION=sqlite` ve `DB_DATABASE=:memory:` ayarlayın
- Dev/prod verilerine dokunmaktan kaçınmak için testler için ayrı env tutun

### Yetkilendirme Testleri

```php
use Illuminate\Support\Facades\Gate;

$this->assertTrue(Gate::forUser($user)->allows('update', $project));
$this->assertFalse(Gate::forUser($otherUser)->allows('update', $project));
```

### Inertia Feature Testleri

Inertia.js kullanırken, Inertia test yardımcıları ile component ismi ve prop'ları doğrulayın.

```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')
        );
    }
}
```

Testleri Inertia yanıtlarıyla uyumlu tutmak için ham JSON assertion'ları yerine `assertInertia` tercih edin.

Related Skills

laravel-plugin-discovery

144923
from affaan-m/everything-claude-code

Discover and evaluate Laravel packages via LaraPlugins.io MCP. Use when the user wants to find plugins, check package health, or assess Laravel/PHP compatibility.

DevelopmentClaude

laravel-verification

144923
from affaan-m/everything-claude-code

Verification loop for Laravel projects: env checks, linting, static analysis, tests with coverage, security scans, and deployment readiness.

DevelopmentClaude

laravel-security

144923
from affaan-m/everything-claude-code

Laravel security best practices for authn/authz, validation, CSRF, mass assignment, file uploads, secrets, rate limiting, and secure deployment.

DevelopmentClaude

laravel-patterns

144923
from affaan-m/everything-claude-code

Laravel architecture patterns, routing/controllers, Eloquent ORM, service layers, queues, events, caching, and API resources for production apps.

DevelopmentClaude

workspace-surface-audit

144923
from affaan-m/everything-claude-code

Audit the active repo, MCP servers, plugins, connectors, env surfaces, and harness setup, then recommend the highest-value ECC-native skills, hooks, agents, and operator workflows. Use when the user wants help setting up Claude Code or understanding what capabilities are actually available in their environment.

DevelopmentClaude

safety-guard

144923
from affaan-m/everything-claude-code

Use this skill to prevent destructive operations when working on production systems or running agents autonomously.

DevelopmentClaude

repo-scan

144923
from affaan-m/everything-claude-code

Cross-stack source code asset audit — classifies every file, detects embedded third-party libraries, and delivers actionable four-level verdicts per module with interactive HTML reports.

DevelopmentClaude

project-flow-ops

144923
from affaan-m/everything-claude-code

Operate execution flow across GitHub and Linear by triaging issues and pull requests, linking active work, and keeping GitHub public-facing while Linear remains the internal execution layer. Use when the user wants backlog control, PR triage, or GitHub-to-Linear coordination.

DevelopmentClaude

manim-video

144923
from affaan-m/everything-claude-code

Build reusable Manim explainers for technical concepts, graphs, system diagrams, and product walkthroughs, then hand off to the wider ECC video stack if needed. Use when the user wants a clean animated explainer rather than a generic talking-head script.

DevelopmentClaude

design-system

144923
from affaan-m/everything-claude-code

Use this skill to generate or audit design systems, check visual consistency, and review PRs that touch styling.

DevelopmentClaude

click-path-audit

144923
from affaan-m/everything-claude-code

Trace every user-facing button/touchpoint through its full state change sequence to find bugs where functions individually work but cancel each other out, produce wrong final state, or leave the UI in an inconsistent state. Use when: systematic debugging found no bugs but users report broken buttons, or after any major refactor touching shared state stores.

DevelopmentClaude

ck

144923
from affaan-m/everything-claude-code

Persistent per-project memory for Claude Code. Auto-loads project context on session start, tracks sessions with git activity, and writes to native memory. Commands run deterministic Node.js scripts — behavior is consistent across model versions.

DevelopmentClaude