← Back to list
writing-feature-tests
by moonpixels
Laravel skeleton application template with Inertia React.
⭐ 1🍴 0📅 Jan 10, 2026
SKILL.md
name: writing-feature-tests description: Write feature tests for HTTP endpoints, controllers, and full request/response cycles using Pest v4. Use when ANY business logic is added to codebase. Feature tests are the PRIMARY testing approach - use for all Controllers, Actions, Form Requests, and application behavior. This is your default testing strategy.
Write Feature Tests
Feature tests are your primary testing approach for all business logic. Write feature tests for ALL logic added to the app, testing the full HTTP request/response cycle. They are fast, comprehensive, and should always be your default starting point.
Testing Hierarchy
- Feature Tests (PRIMARY) - Default for all business logic and HTTP endpoints (you're here)
- Unit Tests (SUPPLEMENTARY) - Sprinkle in for complex, concentrated areas
- Browser Tests (MINIMAL) - Only for core areas and JS interactions
File Structure
tests/Feature/Http/Controllers/{ControllerName}/{MethodName}Test.php
Examples:
tests/Feature/Http/Controllers/Auth/RegisteredUserController/StoreTest.phptests/Feature/Http/Controllers/User/ProfileController/UpdateTest.php
Core Conventions
Test Structure
<?php
declare(strict_types=1);
use App\Models\User;
test('descriptive test name in sentence case', function (): void {
// Arrange
$user = User::factory()->create();
// Act
$response = $this->actingAs($user)->post(route('endpoint'), getData());
// Assert
$response->assertValid()->assertRedirect();
expect($user->fresh())
->property->toBe('expected value');
});
// Helper functions at bottom of file
function getData(array $overrides = []): array
{
return array_merge([
'field' => 'value',
], $overrides);
}
Key Requirements:
- Always include
declare(strict_types=1); - Use
test('description', function (): void {})syntax (Pest v4) - Follow Arrange-Act-Assert (AAA) pattern
- Helper functions at bottom of file
HTTP Methods
$this->get(route('users.index'))
$this->post(route('users.store'), getData())
$this->put(route('users.update', $user), getData())
$this->delete(route('users.destroy', $user))
Authentication
$this->actingAs($user)->get(route('dashboard'))
$this->assertAuthenticated()
$this->assertGuest()
Response Assertions
->assertOk()
->assertCreated()
->assertRedirect(route('dashboard'))
->assertValid()
->assertInvalid(['email'])
->assertJson(['key' => 'value'])
Database Assertions
$this->assertDatabaseHas('users', ['email' => 'test@example.com'])
$this->assertDatabaseMissing('users', ['email' => 'deleted@example.com'])
$this->assertDatabaseCount('users', 5)
Expect Assertions
$user = User::query()->sole();
expect($user)
->name->toBe('Test User')
->email->toBe('test@example.com')
->and($user->posts)->toHaveCount(3);
Anti-Patterns
Don't Do This
// Don't skip return type
test('users can register', function () {});
// Don't hardcode URLs
$this->get('/dashboard');
// Don't create test data inline
$this->post(route('register'), [
'name' => 'Test User',
'email' => 'test@example.com',
]);
Do This Instead
// Always type hint return type
test('users can register', function (): void {});
// Use named routes
$this->get(route('dashboard.index'));
// Use helper functions
function getData(array $overrides = []): array
{
return array_merge([
'name' => 'Test User',
'email' => 'test@example.com',
], $overrides);
}
Running Tests
php artisan test --testsuite=Feature
php artisan test tests/Feature/Http/Controllers/Auth/RegisteredUserController/StoreTest.php
php artisan test --coverage --min=90
php artisan test --filter="new users can register"
Quality Standards
- All feature tests must pass PHPStan level 8
- 100% type coverage required
- 90% overall test coverage required
- Tests must be independent (no test order dependency)
- Use
LazilyRefreshDatabasetrait (configured in Pest.php) - Every controller method must have at least one feature test
- Critical paths must have multiple test cases (happy path + edge cases)
References
- references/examples.md - Complete working examples
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon