All skills
asyrafhussin avatar

/laravel-testing

@a5fe20e

Laravel 13 testing with Pest PHP 4 or PHPUnit 12. Use when writing feature tests, unit tests, or any test code in a Laravel application. Triggers on tasks involving HTTP tests, model factories, database assertions, mocking facades, authentication testing, or test organisation patterns.

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/laravel-testing

This session only. Nothing lands on disk.

rulespest-datasets.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Parameterised Testing — Datasets (Pest) or DataProvider (PHPUnit)

Impact: MEDIUM (Replaces repeated tests with a single parameterised test, improving coverage without duplication)

Pest: Use ->with() to supply datasets. Pest runs the test once per entry, injecting values as function arguments.

PHPUnit: Use #[DataProvider] attribute pointing to a static method that returns arrays of arguments. Note: the @dataProvider annotation was removed in PHPUnit 12 — use the attribute instead.

Bad Example

<?php

// Duplicate tests — only the input differs (bad in both frameworks)
test('title cannot be empty', function () {
    $this->postJson('/api/posts', ['title' => ''])
        ->assertUnprocessable();
});

test('title cannot be null', function () {
    $this->postJson('/api/posts', ['title' => null])
        ->assertUnprocessable();
});

test('title must not exceed 255 characters', function () {
    $this->postJson('/api/posts', ['title' => str_repeat('a', 256)])
        ->assertUnprocessable();
});
// Three identical tests — one parameterised test handles all three

Good Example — Pest

<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

// Inline dataset with named cases
it('rejects invalid post titles', function (mixed $title) {
    $user = User::factory()->create();

    $this->actingAs($user)
        ->postJson('/api/posts', ['title' => $title, 'body' => 'Content'])
        ->assertUnprocessable()
        ->assertJsonValidationErrors(['title']);
})->with([
    'empty string'         => [''],
    'null value'           => [null],
    'too long (256 chars)' => [str_repeat('a', 256)],
    'integer'              => [123],
]);

// Multiple arguments
it('validates login credentials', function (string $email, string $password, string $field) {
    $this->postJson('/api/login', compact('email', 'password'))
        ->assertUnprocessable()
        ->assertJsonValidationErrors([$field]);
})->with([
    'invalid email'  => ['not-an-email', 'secret123', 'email'],
    'empty password' => ['valid@example.com', '', 'password'],
]);

// Named dataset — reusable across multiple tests
dataset('invalid_statuses', [
    'draft'    => ['draft'],
    'archived' => ['archived'],
    'banned'   => ['banned'],
]);

it('rejects invalid post status on update', function (string $status) {
    $user = User::factory()->create();
    $post = Post::factory()->for($user)->create();

    $this->actingAs($user)
        ->patchJson("/api/posts/{$post->id}", ['status' => $status])
        ->assertUnprocessable()
        ->assertJsonValidationErrors(['status']);
})->with('invalid_statuses');

Good Example — PHPUnit

<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;

class PostValidationTest extends TestCase
{
    use RefreshDatabase;

    // DataProvider static method — returns array of [label => [args...]]
    public static function invalidTitles(): array
    {
        return [
            'empty string'         => [''],
            'null value'           => [null],
            'too long (256 chars)' => [str_repeat('a', 256)],
            'integer'              => [123],
        ];
    }

    #[DataProvider('invalidTitles')]
    public function test_rejects_invalid_post_titles(mixed $title): void
    {
        $user = User::factory()->create();

        $this->actingAs($user)
            ->postJson('/api/posts', ['title' => $title, 'body' => 'Content'])
            ->assertUnprocessable()
            ->assertJsonValidationErrors(['title']);
    }

    // Multiple arguments
    public static function invalidCredentials(): array
    {
        return [
            'invalid email'  => ['not-an-email', 'secret123', 'email'],
            'empty password' => ['valid@example.com', '', 'password'],
        ];
    }

    #[DataProvider('invalidCredentials')]
    public function test_validates_login_credentials(
        string $email,
        string $password,
        string $errorField
    ): void {
        $this->postJson('/api/login', compact('email', 'password'))
            ->assertUnprocessable()
            ->assertJsonValidationErrors([$errorField]);
    }
}

Why It Matters

  • DRY: One test body covers many input variations — no copy-paste duplication
  • Coverage: Add cases by appending to the dataset/provider — no new test function needed
  • Clear output: Both Pest and PHPUnit label each run with the dataset key, making failures locatable

Reference: Pest PHP — Datasets · PHPUnit — Data Providers

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill is a comprehensive testing guide for Laravel 13, covering both Pest PHP and PHPUnit frameworks. It provides clear rules and code examples for HTTP testing, model factories, database assertions, and mocking services. No security risks or malicious patterns were identified.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    25 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at a5fe20e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
Other metadata
metadata
{
  "author": "Laravel Community",
  "version": "1.1.0",
  "laravelVersion": "13.x",
  "phpVersion": "8.3+",
  "pestVersion": "4.x",
  "phpunitVersion": "12.x"
}

README badge

README badge for asyrafhussin/agent-skills/laravel-testing