Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Sửa một dòng code mà không dám deploy vì sợ hỏng chỗ khác? Test tự động chính là tấm lưới an toàn cho nỗi sợ đó. Laravel hỗ trợ kiểm thử rất tốt ngay từ khi cài đặt, bài viết này chỉ bạn cách bắt đầu một cách thực tế.
Laravel chia test thành hai loại chính:
Với ứng dụng web, feature test mang lại giá trị lớn nhất cho công sức bỏ ra vì chúng giống cách người dùng thật sự dùng sản phẩm.
Tạo test bằng php artisan make:test PostApiTest, rồi viết:
use Illuminate\Foundation\Testing\RefreshDatabase;class PostApiTest extends TestCase{ use RefreshDatabase; public function test_user_can_create_post(): void { $user = User::factory()->create(); $response = $this->actingAs($user)->postJson('/api/posts', [ 'title' => 'Bài đầu tiên', 'body' => 'Nội dung bài viết đủ dài để hợp lệ.', ]); $response->assertCreated(); $this->assertDatabaseHas('posts', ['title' => 'Bài đầu tiên']); } public function test_guest_cannot_create_post(): void { $this->postJson('/api/posts', [])->assertUnauthorized(); }}Trait RefreshDatabase đưa database về trạng thái sạch cho mỗi test, nên các test không ảnh hưởng nhau. Chạy bằng php artisan test.
Pest là bộ khung kiểm thử xây trên PHPUnit với cú pháp gọn và dễ đọc:
use function Pest\Laravel\{actingAs, postJson};it('lets a user create a post', function () { $user = User::factory()->create(); actingAs($user); postJson('/api/posts', ['title' => 'Bài đầu tiên', 'body' => 'Nội dung đủ dài để hợp lệ.']) ->assertCreated();});it('rejects guests', function () { postJson('/api/posts', [])->assertUnauthorized();});Cả hai đều chạy được trong cùng dự án, bạn chọn phong cách mình thích. Kiến thức về assertion và factory dùng chung cho cả hai.
Factory sinh dữ liệu mẫu để test không phải tạo thủ công từng trường:
Post::factory()->count(3)->for($user)->create();Với dịch vụ bên ngoài như gửi mail hay gọi API thanh toán, hãy dùng fake có sẵn: Mail::fake(), Queue::fake(), Http::fake(). Test sẽ nhanh, ổn định và không gửi thư thật ra ngoài.
Mail::fake();// ... thực hiện hành độngMail::assertSent(WelcomeMail::class);Đừng đặt mục tiêu phủ 100% ngay. Một bộ test nhỏ nhưng chạy ổn định mỗi lần commit còn tốt hơn một bộ đồ sộ mà không ai dám chạy.
Test chỉ có giá trị nếu được chạy thường xuyên. Hãy chạy chúng tự động trên CI mỗi khi có pull request, và coi test đỏ là lý do dừng merge. Dùng database SQLite trong bộ nhớ hoặc một database riêng cho test để chạy nhanh và an toàn.
Test tốt cần đọc như một mô tả hành vi. Hãy đặt tên theo điều mong đợi, ví dụ test_guest_cannot_create_post, để khi test lỗi bạn hiểu ngay thứ gì đang hỏng. Mỗi test chỉ nên kiểm tra một khía cạnh, chuẩn bị dữ liệu bằng factory thay vì phụ thuộc dữ liệu có sẵn, và không để test này phụ thuộc kết quả của test khác. Tránh kiểm tra chi tiết cài đặt bên trong; hãy kiểm tra kết quả nhìn thấy được như mã trạng thái, nội dung JSON và dữ liệu đã lưu.
Cuối cùng, hãy giữ cho bộ test chạy nhanh. Nếu mất mười phút mới có kết quả, mọi người sẽ ngừng chạy nó. Tách các test chậm (gọi dịch vụ thật, trình duyệt) khỏi nhóm test chạy hằng ngày, và dùng php artisan test --parallel để tận dụng nhiều nhân CPU khi bộ test lớn dần.
Khi API dùng token, bạn không cần đi qua bước đăng nhập trong mỗi test. Hãy dùng actingAs($user, 'sanctum') để giả lập người dùng đã xác thực, và dành riêng một vài test cho chính luồng đăng nhập. Cách chia này giữ cho test nhanh mà vẫn bao phủ các điểm quan trọng. Với các endpoint trả về danh sách, nên kiểm tra cả cấu trúc JSON bằng assertJsonStructure để chắc chắn ứng dụng khách nhận đúng các trường mà nó cần.
Bắt đầu nhỏ: một test cho luồng đăng nhập, một test cho phân quyền, rồi tăng dần. Sau vài tuần, bạn sẽ thấy việc sửa code bớt đáng sợ hơn hẳn, và đó là phần thưởng lớn nhất của kiểm thử tự động.
Muốn học bài bản và có lộ trình rõ ràng? Bạn có thể xem các khóa học trên codebem.com.
Nguyễn Đình Cường
0 comment