JavaScript, APIs, and the Frontend
Testing Your Code
Feature tests, what to test first, and TDD basics
Why Test?
Tests catch bugs before your users do. More importantly, they give you confidence to change code. Without tests, every refactor is a gamble. With tests, you can modify code and know within seconds if something broke.
Feature Tests in Laravel
Laravel's feature tests make HTTP requests to your application and assert on the response. They test the full stack — routing, middleware, controllers, database:
class PostTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_create_post(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', [
'title' => 'Test Post',
'body' => 'Test content',
]);
$response->assertRedirect('/posts');
$this->assertDatabaseHas('posts', ['title' => 'Test Post']);
}
public function test_guest_cannot_create_post(): void
{
$response = $this->post('/posts', [
'title' => 'Test Post',
]);
$response->assertRedirect('/login');
}
}
The RefreshDatabase trait resets the database between tests so each test starts fresh.
What to Test First
You don't need 100% coverage. Start with the highest-value tests:
- Authentication and authorization — Can the right people access the right things? Can wrong people be kept out?
- Data creation and modification — Do forms and API endpoints create/update the correct records?
- Business logic — Calculations, state transitions, rules that matter to the business.
- Edge cases you've already been burned by — Turn every bug fix into a test.
The best test to write first is the one that would have caught the bug you just spent an hour debugging.
TDD Basics
Test-Driven Development follows a simple cycle:
- Red — Write a failing test for the feature you want.
- Green — Write the minimum code to make the test pass.
- Refactor — Clean up the code while keeping tests green.
TDD forces you to think about the interface before the implementation. It's not always practical for every feature, but it's excellent for complex business logic and API endpoints.
Asserting API Responses
public function test_api_returns_posts(): void
{
Post::factory()->count(3)->create();
$response = $this->getJson('/api/posts');
$response->assertOk()
->assertJsonCount(3, 'data')
->assertJsonStructure([
'data' => [
'*' => ['id', 'title', 'body', 'created_at'],
],
]);
}
public function test_api_validates_post_creation(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->postJson('/api/posts', []);
$response->assertUnprocessable()
->assertJsonValidationErrors(['title', 'body']);
}
Key Takeaways
- Feature tests test the full stack. They're the highest-value tests in a Laravel app.
- Test auth, data creation, and business logic first. Not everything needs a test.
- TDD (Red → Green → Refactor) is excellent for complex logic and APIs.
- Use
assertJsonStructure(),assertJsonValidationErrors(), andassertDatabaseHas()for confident assertions.
Ask me anything about this lesson.
I have the full lesson content as context.