Chiến lược kiểm thử phần mềm thường được mô tả bằng độ bao phủ, và độ bao phủ lại là con số ít thông tin nhất trong toàn bộ lĩnh vực này. Một mã nguồn đạt chín mươi phần trăm vẫn có thể đẩy lỗi ra đúng luồng được dùng nhiều nhất, bởi độ bao phủ chỉ đo xem những dòng nào đã chạy trong một lần chạy kiểm thử, chứ không đo xem có điều gì có ý nghĩa được khẳng định về chúng hay không.
Những đội tin tưởng bộ kiểm thử của mình không phải là đội có tỷ lệ cao nhất. Đó là những đội mà bài kiểm thử chỉ đỏ khi thứ gì đó thực sự hỏng và im lặng trong mọi trường hợp còn lại, một phẩm chất hóa ra khó mua hơn nhiều.
Câu hỏi đáng đặt ra với bất kỳ bài kiểm thử nào: nếu nó đỏ, tôi có biết phải làm gì không? Một bài kiểm thử đỏ vì hành vi đã thay đổi thì nói cho bạn điều gì đó. Một bài kiểm thử đỏ vì một chi tiết cài đặt bị di chuyển thì chỉ nói rằng ai đó vừa tái cấu trúc, và sau đủ nhiều lần như vậy, cả đội thôi đọc lỗi và chỉ chạy lại pipeline cho đến khi nó xanh.
Vì sao độ bao phủ gây hiểu lầm
Độ bao phủ trả lời câu hỏi dòng này đã chạy hay chưa, khác hẳn với câu hỏi dòng này có đúng hay không. Một bài kiểm thử gọi một hàm mà không khẳng định điều gì tạo ra đúng cùng mức độ bao phủ như một bài kiểm tra mọi nhánh của kết quả.
Khoảng cách đó có hệ quả thực tế. Mục tiêu đặt ở một tỷ lệ phần trăm cố định luôn tạo ra những bài kiểm thử viết ra chỉ để chạm tới con số: kiểm thử cạn kiệt trên các getter tầm thường, không có gì trên luồng thanh toán nơi các nhánh khó dựng. Con số đi lên, rủi ro không nhúc nhích.
Độ bao phủ chỉ hữu ích theo một chiều. Độ bao phủ thấp ở một vùng trọng yếu là tín hiệu thật, đáng để hành động. Độ bao phủ tổng thể cao không chứng minh điều gì, và coi nó là mục tiêu thay vì một phép chẩn đoán chính là cách các đội kết thúc với hàng nghìn bài kiểm thử mà không có chút niềm tin nào.
Chiến lược kiểm thử phần mềm: bài kiểm thử nào đáng giá
Mỗi bài kiểm thử vừa là tài sản vừa là gánh nặng. Nó phải được bảo trì, nó làm chậm bộ kiểm thử, và đôi khi chính nó sai. Câu hỏi hữu ích là bài nào hoàn vốn.
Kiểm thử đơn vị hoàn vốn khi logic thực sự phức tạp và độc lập với hạ tầng: quy tắc tính giá, xử lý ngày tháng, kiểm tra quyền, bộ phân tích cú pháp. Nhanh, chính xác, và chúng sống sót qua tái cấu trúc vì hành vi mà chúng mô tả là có thật.
Kiểm thử tích hợp hoàn vốn nhiều hơn phần lớn các đội tưởng, vì đa số lỗi trên môi trường thật nằm ở ranh giới chứ không nằm bên trong các hàm. Câu truy vấn chạy tốt với mock nhưng gãy với cơ sở dữ liệu thật. API có trường tùy chọn mà trên thực tế luôn vắng mặt. Những bài này chậm hơn và xứng đáng.
Kiểm thử đầu cuối chỉ hoàn vốn cho một nhúm hành trình, và số lượng phải đủ nhỏ để đọc to lên được. Đăng ký, mua hàng, đúng một việc mà doanh nghiệp của bạn làm. Chúng chậm, dễ vỡ và tốn kém, và một bộ hai trăm bài như thế là nguồn khổ sở chính của một đội.
Hình dạng mà phần lớn mã nguồn hội tụ về là nhiều kiểm thử đơn vị, một lớp kiểm thử tích hợp vững chắc và một nhúm hành trình đầu cuối, tức là kim tự tháp kiểm thử mà Martin Fowler mô tả. Chỗ các đội đi sai thường là phần giữa: họ có kiểm thử đơn vị và kiểm thử đầu cuối, còn gần như không có gì kiểm tra xem các mảnh có khớp với nhau hay không.
Test không ổn định là vấn đề niềm tin
Một bài kiểm thử đỏ một lần trong hai mươi lần chạy còn tệ hơn là không có bài kiểm thử nào, và lý do thuộc về hành vi con người chứ không phải kỹ thuật.
Khi bộ kiểm thử đã có vài bài chập chờn, cả đội học được rằng đỏ không nhất thiết là hỏng. Chạy lại trở thành thói quen. Rồi một lần đỏ thật cũng bị chạy lại, và khi nó xanh ở lần thử thứ ba, ai đó gộp nó vào. Bộ kiểm thử đã ngừng hoạt động như một tín hiệu trong khi vẫn tiếp tục ngốn thời gian.
Hãy coi sự chập chờn là một khiếm khuyết có cùng mức ưu tiên với lỗi trên môi trường thật. Cách ly bài kiểm thử đó ngay lập tức để pipeline xanh một cách trung thực, rồi sửa hoặc xóa nó. Nguyên nhân thường gặp là trạng thái dùng chung giữa các bài kiểm thử, phụ thuộc vào thời gian thực và trông cậy vào thứ tự chạy mà trình chạy không hề bảo đảm.
Xóa một bài kiểm thử chập chờn là một kết cục hợp lệ. Bài kiểm thử không ai tin thì chẳng bảo vệ được gì, và bỏ nó đi ít nhất cũng chấm dứt việc nó ngốn sự chú ý.
Kiểm thử hành vi, không kiểm thử cài đặt
Nguyên nhân phổ biến nhất của những bộ kiểm thử đắt đỏ là các bài kiểm thử bị buộc chặt vào cách mã hoạt động thay vì vào việc mã làm gì.
Mock mọi phụ thuộc rồi khẳng định rằng một phương thức cụ thể đã được gọi với các đối số cụ thể sẽ tạo ra bài kiểm thử đỏ sau mọi lần tái cấu trúc, bất kể hành vi có thay đổi hay không. Điều đó ngược hoàn toàn: tái cấu trúc chính là lúc bạn cần bộ kiểm thử nói rằng không có gì hỏng, thế mà nó lại tạo ra năm mươi lần đỏ để bạn ngồi rà bằng tay.
Cách làm thay thế là khẳng định trên kết quả. Với đầu vào này, hệ thống tạo ra đầu ra này hoặc đạt tới trạng thái này. Những bài kiểm thử như vậy sống sót qua các lần viết lại phần ruột, nghĩa là chúng tiếp tục bảo vệ bạn đúng trong những thay đổi mang nhiều rủi ro nhất.
Mock xứng đáng có chỗ ở những ranh giới thật: một nhà cung cấp thanh toán, một dịch vụ email, bất cứ thứ gì chậm hoặc có tác dụng phụ mà bạn không thể để xảy ra trong một lần chạy kiểm thử. Bên trong mã của chính bạn, chúng thường tốn nhiều hơn phần trả lại.
Cho nó chạy được trong CI
Bộ kiểm thử mà không ai chờ là bộ kiểm thử sẽ bị bỏ qua. Nếu chạy đầy đủ mất bốn mươi phút, người ta push rồi đi làm việc khác, và phản hồi chỉ tới khi họ đã bắt đầu chuyện khác.
Hãy tách nó ra. Kiểm thử đơn vị và tích hợp nhanh chạy ở mỗi lần push, cho câu trả lời trong vài phút. Các hành trình đầu cuối chậm chạy khi gộp nhánh hoặc theo lịch. Đây cũng chính là lối tư duy về kỷ luật triển khai trong hướng dẫn thực hành tốt nhất CI/CD cho các nhóm phát triển tại Anh năm 2026 của chúng tôi.
Hãy làm cho thông báo lỗi dễ đọc. Một lần đỏ chỉ nói rằng một khẳng định là sai, không hề cho biết đang kiểm tra điều gì, sẽ ngốn mười phút khảo cổ mỗi lần. Đặt tên bài kiểm thử theo hành vi mà nó bảo vệ sẽ biến danh sách lỗi thành bản mô tả những gì vừa hỏng.
Và hãy giữ bộ kiểm thử tất định. Không gọi mạng thật, không phụ thuộc vào ngày hôm nay mà không kiểm soát nó, không giả định về thứ tự. Mỗi bài kiểm thử phi tất định là một bài chập chờn trong tương lai.
Bắt đầu từ đâu với mã nguồn chưa có kiểm thử
Đừng cố đạt độ bao phủ đầy đủ theo kiểu hồi tố; công sức là khổng lồ và phần lớn trong đó bảo vệ đoạn mã chẳng ai đụng tới.
Hãy bắt đầu từ những luồng mà một lỗi làm mất tiền, và viết kiểm thử tích hợp quanh chúng trước, vì chúng bắt được nhiều nhất trên mỗi bài kiểm thử được viết. Sau đó, thêm một bài kiểm thử cho mỗi lần sửa lỗi, tái hiện lỗi trước khi vá. Nhờ vậy, độ bao phủ lớn lên đúng nơi khiếm khuyết thực sự xuất hiện, và đó là tín hiệu tốt nhất bạn có về nơi rủi ro trú ngụ.
Mecanik rà soát và xây dựng chiến lược kiểm thử như một phần trong dịch vụ phát triển phần mềm theo yêu cầu của chúng tôi, thường bắt đầu bằng câu hỏi những lần hỏng nào sẽ thực sự gây đau. Nếu bộ kiểm thử của bạn đồ sộ mà đội vẫn triển khai trong lo lắng, vấn đề hiếm khi nằm ở số lượng bài kiểm thử.
Đọc thêm: Tài liệu kỹ thuật thực sự có người đọc , Onboarding lập trình viên ra sản phẩm ngay tuần đầu , Postmortem thực sự thay đổi được điều gì đó và Đánh phiên bản API: khi nào phá vỡ và cách tránh .
Câu hỏi thường gặp
Độ bao phủ kiểm thử cao có phải mục tiêu tốt không? Tự thân nó thì không. Độ bao phủ đo xem những dòng nào đã chạy trong một lần chạy kiểm thử, chứ không đo xem có điều gì có ý nghĩa được khẳng định về chúng, nên một bài gọi hàm mà không khẳng định gì lại đạt điểm ngang bằng một bài kiểm tra mọi nhánh. Độ bao phủ thấp trên một luồng trọng yếu là tín hiệu hữu ích; tỷ lệ tổng thể cao thì chứng minh được rất ít.
Tỷ lệ hợp lý giữa kiểm thử đơn vị, tích hợp và đầu cuối là gì? Nhiều kiểm thử đơn vị cho phần logic thực sự phức tạp, một lớp kiểm thử tích hợp dày dặn vì đa số lỗi trên môi trường thật nằm ở ranh giới, và một số ít hành trình đầu cuối mà bạn có thể đọc to lên được. Phần lớn các đội làm sai lớp giữa: có kiểm thử đơn vị và đầu cuối nhưng rất ít thứ kiểm tra xem các mảnh có khớp nhau hay không.
Tôi nên xử lý test không ổn định thế nào? Hãy coi chúng là khiếm khuyết với mức ưu tiên của lỗi trên môi trường thật. Cách ly bài kiểm thử ngay lập tức để pipeline vẫn trung thực, rồi sửa hoặc xóa nó. Khi bộ kiểm thử đã có vài bài chập chờn, cả đội học được rằng đỏ không có nghĩa là hỏng, chạy lại theo phản xạ, và cuối cùng gộp vào một lần đỏ thật. Xóa một bài kiểm thử chập chờn là kết cục hợp lệ.
Tôi có nên mock các phụ thuộc trong kiểm thử không? Ở những ranh giới thật thì có: nhà cung cấp thanh toán, dịch vụ email, bất cứ thứ gì chậm hoặc có tác dụng phụ. Bên trong mã của chính bạn, mock thường tốn nhiều hơn phần trả lại, vì khẳng định rằng một phương thức cụ thể đã được gọi với các đối số cụ thể sẽ làm bài kiểm thử đỏ sau mọi lần tái cấu trúc, bất kể hành vi có thay đổi hay không.
Làm sao thêm kiểm thử vào mã nguồn chưa có bài nào? Đừng cố đạt độ bao phủ đầy đủ theo kiểu hồi tố. Hãy viết kiểm thử tích hợp quanh những luồng mà một lỗi làm mất tiền, vì chúng bắt được nhiều nhất trên mỗi bài kiểm thử được viết. Sau đó thêm một bài kiểm thử cho mỗi lần sửa lỗi, tái hiện lỗi trước khi vá, để độ bao phủ lớn lên đúng nơi khiếm khuyết thực sự xuất hiện.
Bình luận