Testing

Unit Testing

Unit tests verify the smallest parts of your application (methods, functions, classes) in isolation. Use Pest for all unit tests. Place unit tests in the tests/Unit directory.

// Example: User model unit test
it('gets the full name', function () {
    $user = new User(['first_name' => 'John', 'last_name' => 'Doe']);
    expect($user->full_name)->toBe('John Doe');
});
  • Use descriptive test names.
  • Mock dependencies to isolate the unit under test.
  • Test edge cases and invalid input.

Feature Testing

Feature tests verify the behavior of your application as a whole, including HTTP requests, database interactions, and middleware. Place feature tests in the tests/Feature directory.

it('registers a user', function () {
    $response = $this->post('/register', [
        'name' => 'Jane Doe',
        'email' => 'jane@example.com',
        'password' => 'password',
        'password_confirmation' => 'password',
    ]);
    $response->assertRedirect('/home');
    expect(User::where('email', 'jane@example.com'))->toBeTruthy();
});
  • Use Pest's HTTP helpers (get, post, put, delete).
  • Assert responses, redirects, and database changes.
  • Test authentication, authorization, and validation.

Integration Testing

Integration tests verify that multiple parts of your application work together (e.g., controllers, models, services). Use integration tests for complex workflows.

it('allows a user to create a post', function () {
    $user = User::factory()->create();
    $this->actingAs($user);
    $response = $this->post('/posts', [
        'title' => 'Test Post',
        'body' => 'This is a test.',
    ]);
    $response->assertStatus(201);
    expect(Post::where('title', 'Test Post'))->toBeTruthy();
});

Mocking

Use mocking to isolate tests from external dependencies (e.g., services, APIs). Use Pest's mocking capabilities or Laravel's built-in mocking tools.

it('gets the name using a mock', function () {
    $user = Mockery::mock(User::class);
    $user->shouldReceive('getName')->andReturn('John Doe');
    expect($user->getName())->toBe('John Doe');
});
  • Mock services, repositories, and events.
  • Use dependency injection for easier mocking.

Best Practices

  • Write tests for all new features and bug fixes.
  • Use factories and seeders for test data.
  • Run tests automatically in CI/CD pipelines.
  • Use descriptive test names and group related tests in files.
  • Aim for high code coverage, but prioritize meaningful tests over coverage percentage.

Example: Pest Test File Structure

// tests/Feature/InvoiceTest.php
it('creates an invoice', function () {
    // ...
});
it('calculates the invoice total correctly', function () {
    // ...
});