مقاله

with()، dataset اشتراکی، expectation سفارشی و ترکیب با Feature test — کمتر تکرار، پوشش بیشتر.

Pest Dataset و Custom Expectation — تست پارامتریک حرفه‌ای در Laravel

Pest Dataset و Custom Expectation — تست پارامتریک حرفه‌ای در Laravel

وقتی ده تست فقط input متفاوت دارند، copy-paste test شلخته می‌شود. Pest با with() و dataset همان ایده PHPUnit Data Provider را خوش‌خوان‌تر می‌کند. Custom expectation هم assertion تکراری تیم را یک‌بار تعریف و همه‌جا reuse می‌کند.

with() — dataset inline

it('validates slug format', function (string $slug, bool $valid) {
    $result = SlugValidator::check($slug);
    expect($result)->toBe($valid);
})->with([
    ['my-post', true],
    ['My Post!', false],
    ['', false],
    ['a-b-c-123', true],
]);

هر ردیف یک اجرای جدا — failure دقیقاً همان case را نشان می‌دهد.

dataset نام‌دار — reuse

// tests/Datasets/Slugs.php
dataset('invalid_slugs', [
    'empty' => [''],
    'spaces' => ['hello world'],
    'unicode' => ['مقاله'],
]);

it('rejects invalid slugs', function (string $slug) {
    expect(SlugValidator::check($slug))->toBeFalse();
})->with('invalid_slugs');

dataset در چند فایل test مشترک — یک منبع truth.

dataset با closure

dataset('users', function () {
    yield 'admin' => [User::factory()->admin()->create()];
    yield 'guest' => [User::factory()->create()];
});

برای model از DB — در Feature test با RefreshDatabase. Feature test.

Custom Expectation

// tests/Pest.php
expect()->extend('toBePublished', function () {
    return $this->value->status === 'published'
        && $this->value->published_at !== null;
});

expect()->extend('toBeIranianMobile', function () {
    return expect($this->value)->toMatch('/^09\d{9}$/');
});
it('post is published', function () {
    $post = Post::factory()->published()->create();
    expect($post)->toBePublished();
});

خوانایی بالا — Clean Code در تست.

expectation روی نوع

expect()->intercept('json', JsonResponse::class, function ($json) {
    return expect($json->getData(true));
});

// expect($response)->json()->toHaveKey('data');

برای API — Error handling.

describe + dataset

describe('VAT calculation', function () {
    it('calculates correctly', function (int $amount, int $vat) {
        expect(calculateVat($amount))->toBe($vat);
    })->with([
        [1000, 90],
        [0, 0],
    ]);
});

نام تست از dataset

it('validates :slug', function (string $slug) {
    // ...
})->with(['a', 'b']);

placeholder در عنوان — debug راحت‌تر.

اشتباهات

  • dataset ۱۰۰۰ ردیف بدون گروه‌بندی — کند و noisy
  • logic سنگین در dataset closure هر test
  • expectation سفارشی بیش از حد generic

جمع‌بندی

Dataset و expectation تست را DRY و readable می‌کنند. پایه: معرفی Pest. بعدی: تست Action.

راه‌اندازی Pest در پروژه