Hôm nào bạn cũng nghe một nhà phát triển than "chúng tôi không có thời gian viết test". Mỗi lần nghe vậy, tôi lại nhớ đến một dự án cách đây 3 năm - team giao hàng trong 2 tuần, không có test nào, chỉ có manual testing. Và bạn đoán xem? Sau 3 tuần, một bug nhỏ đã khiến hệ thống mất dữ liệu của 5000 người dùng. Lúc đó mới hiểu: viết test không phải để kéo dài thời gian, mà để tiết kiệm thời gian - và công sức.
Tại sao strategy lại quan trọng?
Vấn đề không phải là "nên test không", mà là test cái gì, lúc nào, bằng cách nào. Theo Gartner, 45% các bug production đi qua vì chiến lược kiểm thử không phù hợp, không phải vì lỗi trong test code.
Lối mắc phổ biến: team viết hàng tấn unit test cho những hàm utility nhỏ, rồi để các workflow chính của ứng dụng không có test. Hay ngược lại, chỉ viết end-to-end test rồi chải hết 45 phút cho một lần run. Đó chính là lý do tại sao cần một chiến lược.
Pyramid testing: Cân bằng là chìa khóa
Cấu trúc test pyramid vẫn còn đúng nhưng nhiều người hiểu sai. Không phải là "unit test càng nhiều càng tốt", mà là một tỷ lệ hợp lý:
70% Unit Test (Jest, Vitest, unittest): Nhanh, chi phí thấp, dễ maintain
20% Integration Test: Test khi các component gắn lại - đây là nơi discover bug thực tế nhất
10% E2E Test (Cypress, Playwright): Chỉ test workflow quan trọng nhất, user path chính
Một team Việt Nam mình biết (fintech) đảo ngược pyramid - 50% E2E test, test suite chạy hết 2 tiếng. Tất nhiên developer không chạy test trước khi push (nó quá lâu), dẫn đến merge code không đủ tự tin. Họ đổi khoảng 6 tháng rồi đưa vào pyramid đúng cách, thời gian CI/CD giảm từ 2h xuống còn 12 phút.
Chia sẻ bài viết
Bài viết liên quan
Bạn cần tư vấn về công nghệ?
Đội ngũ Idflow luôn sẵn sàng hỗ trợ bạn trong hành trình chuyển đổi số.
Một insight ít ai đề cập: không phải mọi test đều thuộc unit hoặc E2E. Có cái gọi là contract test - khi backend và frontend phát triển độc lập, thay vì chờ frontend chạy E2E, cả hai team viết test để verify API contract. Công cụ như Pact hoặc simple mock validation giúp phát hiện breaking change sớm.
Thêm nữa là visual regression test - quan trọng lắm nhưng hay bị bỏ qua. Một line CSS change có thể break layout ở mobile mà unit test không bao giờ phát hiện. Công cụ như Percy hoặc Chromatic chạy nhanh, giá rẻ, nhưng giải quyết được cả loạt bug không ai thấy đến lúc production.
Coverage là fake metric
Cần chỉ số coverage, nhưng 100% coverage không bao giờ = zero bugs. Tôi từng thấy code có 95% coverage nhưng vẫn crash vì test chỉ "execute" code, không "verify" hành vi. Test "có" một function nhưng assertion nó chỉ kiểm expect(fn).toBeDefined(). Điều này xảy ra khi team chỉ quan tâm đến con số coverage, không phải chất lượng test.
Thay vào đó, focus vào mutation testing - tự động sửa code một chút (swap > thành <, loại bỏ statement) rồi xem test có fail không. Nếu test vẫn pass khi code bị đột biến, nghĩa là test không kiểm tra gì cả. Công cụ như Stryker (TypeScript/JavaScript) hay Pitest (Java) đơn giản nhưng lộ ra sự thật khắc nghiệt.
Automation là phần dễ, culture là phần khó
Bất kỳ developer nào cũng có thể setup Jest + Cypress trong một buổi chiều. Nhưng khiến cho team thực sự viết test, review test, refactor test? Đó là thử thách thực sự.
Một chiến lược phổ biến là TDD lite - không bắt buộc viết test trước code, nhưng trước khi tạo PR, mọi feature phải có test, được review cùng code. Ở đây reviewer không chỉ kiểm code, mà cả kiểm test logic, edge case.
Con số: Theo Stack Overflow 2023, 56% developer viết test, nhưng chỉ 34% trong đó thực sự theo quy trình test-first hoặc test-along. Phần lớn viết test sau, nhanh gọn, không đủ sâu.
Cân cân bạch, định hướng rõ
Một chiến lược kiểm thử thực sự phải trả lời:
1Feature nào cần test coverage cao? (auth, payment, core logic = 80%+; UI chỉ 60%)
2Test suite chạy bao lâu? (local < 5 phút, CI < 15 phút)
3Test failure nào là critical? (không phải mọi test fail đều block deploy)