Viết unit test bằng AI: tạo ca kiểm thử và phát hiện khoảng trống

Viết unit test bằng AI: tạo ca kiểm thử và phát hiện khoảng trống

Chia sẻ kiến thức 03/11/2026

Viết unit test bằng AI giúp gợi ý test từ hợp đồng hàm, ví dụ và nhánh logic. Xem code tạo được là bản nháp: kỹ sư xác minh assertion, thêm ca biên, chạy test và đối chiếu yêu cầu. Coverage cao hoặc test xanh không chứng minh hành vi đã được kiểm tra đầy đủ.

Kỹ sư đối chiếu unit test AI gợi ý với hợp đồng của hàm
Expected behavior cần có căn cứ trước khi test được chấp nhận.

Unit test kiểm tra điều gì?

Unit test kiểm tra hành vi của một đơn vị code trong điều kiện xác định, thường cô lập phụ thuộc bên ngoài để kết quả dễ tái lập. Một test hữu ích nói rõ bối cảnh, thao tác và kết quả mong đợi. Với chức năng tính phí, chẳng hạn, test có thể xác nhận quy tắc ở ngay dưới ngưỡng, đúng ngưỡng, vượt ngưỡng và đầu vào không hợp lệ.

AI có thể đọc đoạn code, đặc tả hoặc ví dụ test có sẵn rồi gợi ý các trường hợp chưa được bao phủ. Nó cũng có thể tạo cấu trúc theo framework đang dùng, nhưng đôi khi tự giả định quy tắc chưa có trong yêu cầu. Nếu code hiện tại có bug, mô hình có thể tạo test khẳng định chính bug đó là hành vi đúng; vì vậy cần dựa vào hợp đồng hoặc quyết định sản phẩm, không chỉ vào implementation.

Trước khi sinh test, hỏi: “Hành vi nào cần giữ ổn định?” chứ không chỉ “test code này”. Nếu mục tiêu là refactor mà không đổi hành vi, lấy test baseline từ yêu cầu đã được xác nhận. Nếu mục tiêu là sửa lỗi, trước hết tái hiện lỗi bằng một test thất bại; sau sửa, test chuyển xanh nhưng vẫn cần kiểm tra có thực sự tái hiện nguyên nhân mong muốn.

Nguyên liệu cần cung cấp cho AI

Ngữ cảnh tốt giúp test phản ánh hành vi thay vì chỉ lặp lại từng dòng code. Cung cấp các thuộc tính cần thiết, tránh gửi repository hoặc dữ liệu thật rộng hơn mục đích.

  • Contract của hàm: đầu vào, đầu ra, lỗi, side effect và điều kiện tiền/hậu nếu đã định nghĩa.
  • Quy tắc nghiệp vụ: giới hạn, thứ tự ưu tiên, cách xử lý ngoại lệ và quy tắc làm tròn/định dạng.
  • Ví dụ chuẩn: một vài cặp input/output do nhóm xác nhận, có giải thích vì sao đúng.
  • Ca biên: giá trị rỗng, biên số, ngày giờ, ký tự Unicode, tập phần tử trùng hoặc trạng thái thiếu.
  • Framework và convention: runner, assertion library, cách đặt tên, fixture và vị trí test.
  • Ranh giới phụ thuộc: điều gì nên mock/fake và điều gì cần test tích hợp riêng.
  • Phạm vi thay đổi: chỉ tạo test hay được phép sửa production code; nếu chỉ muốn test thì nêu rõ.
Thông tin đưa vào Test được cải thiện Nếu thiếu thì dễ gặp
Quy tắc và ví dụ kết quả Assertion gắn với mục tiêu người dùng/nghiệp vụ. Test phản chiếu implementation hiện có, kể cả hành vi sai.
Giá trị biên Test boundary và off-by-one ở ngưỡng. Chỉ kiểm tra trường hợp bình thường, bỏ sót thay đổi một đơn vị.
Quy tắc lỗi Test exception, message/code nếu là contract. Test chấp nhận lỗi không đúng loại hoặc bỏ qua lỗi.
Framework/convention Test chạy được trong môi trường repository. Code test dùng API không tồn tại hoặc pattern khó bảo trì.
Ranh giới dependency Mock vừa đủ và có thể kiểm tra tương tác cần thiết. Mock che lỗi wiring hoặc test phụ thuộc quá nhiều chi tiết nội bộ.
Các nhóm ca unit test từ trường hợp chuẩn tới biên và lỗi
Chọn ca theo contract thay vì tạo test thật nhiều.

Nhóm ca kiểm thử nên có

Không phải hàm nào cũng cần mọi loại test. Dùng các nhóm dưới đây như câu hỏi để chọn ca theo contract:

  1. Trường hợp hợp lệ điển hình: xác nhận hành vi phổ biến với đầu vào bình thường.
  2. Giá trị biên: ngay dưới, tại và ngay trên ngưỡng; danh sách rỗng, một phần tử, hoặc kích thước tối đa đã quy định.
  3. Giá trị không hợp lệ: kiểu dữ liệu sai, trường bắt buộc thiếu, số ngoài miền hoặc định dạng không được chấp nhận.
  4. Điều kiện kết hợp: hai lựa chọn tương tác, thứ tự ưu tiên hoặc quy tắc bị ảnh hưởng bởi cờ cấu hình.
  5. Ca lỗi: phụ thuộc báo lỗi, timeout, dữ liệu thiếu hoặc exception; kiểm tra phản ứng được đặc tả.
  6. Tính không đổi: kết quả giữ cùng một quy tắc khi đầu vào tương đương hoặc khi sắp xếp không ảnh hưởng contract.
  7. Side effect: chỉ xác nhận lời gọi tới dependency khi đó là cam kết bên ngoài quan trọng, chẳng hạn gửi sự kiện một lần.

Một danh sách dài không đồng nghĩa test tốt. Test cần phân biệt được hành vi đúng và sai. Nếu assertion chỉ xác nhận hàm trả về một object không rỗng, nó có thể không bắt được trường sai. Nếu assertion cố định toàn bộ cấu trúc nội bộ, thay đổi refactor vô hại có thể làm test vỡ liên tục. Chọn điều quan sát được mà người dùng hoặc thành phần gọi hàm dựa vào.

Ví dụ và prompt

Xét hàm tính phí giao hàng nhận trọng lượng, khu vực và loại dịch vụ. Yêu cầu sản phẩm ghi mức phí cơ bản, ngưỡng miễn phí theo vùng, giới hạn trọng lượng và điều kiện loại dịch vụ không hỗ trợ. AI có thể đề xuất test cho từng quy tắc, nhưng đội ngũ cần xác nhận ngưỡng lấy từ đặc tả hiện hành, không suy ra từ tên biến hay giá trị đang nằm trong code.

Chẳng hạn, bảng test có thể kiểm tra một đơn dưới ngưỡng, đúng bằng ngưỡng, cao hơn ngưỡng, trọng lượng âm và khu vực không nhận dịch vụ. Với mỗi ca, ghi input có ý nghĩa, output mong đợi và nguồn quy tắc. Trường hợp `0` khác `null` nếu contract phân biệt; không gộp hai giá trị vì chúng có vẻ “rỗng”.

Để thấy khác biệt giữa một ví dụ chung và một test có expected value rõ, giả sử contract được owner xác nhận: đơn nặng từ 0 đến 5 kg (tính cả 5 kg) có phí 25.000 đồng; trên 5 kg đến 10 kg có phí 40.000 đồng; trọng lượng âm hoặc trên 10 kg phải báo lỗi. Bộ test pytest có thể diễn đạt đúng các ranh giới đó:

import pytest

def shipping_fee(weight_kg):
    if weight_kg < 0 or weight_kg > 10:
        raise ValueError("weight must be between 0 and 10 kg")
    return 25_000 if weight_kg <= 5 else 40_000

def test_shipping_fee_boundaries():
    assert shipping_fee(0) == 25_000
    assert shipping_fee(5) == 25_000
    assert shipping_fee(5.01) == 40_000
    assert shipping_fee(10) == 40_000

@pytest.mark.parametrize("weight", [-0.01, 10.01])
def test_out_of_range_weight_is_rejected(weight):
    with pytest.raises(ValueError):
        shipping_fee(weight)

Trong ví dụ này, mức phí chỉ là dữ kiện minh họa đã được giả định trong contract, không phải quy tắc của một dịch vụ thật. Nếu nhóm chưa xác nhận cách tính tại đúng 5 kg hoặc tối đa 10 kg, chưa nên khẳng định các expected value; hỏi owner rồi mới đưa vào test. Ví dụ cũng cho thấy ca biên cần kiểm tra giá trị ở cả hai phía của ngưỡng.

Dùng prompt sau để yêu cầu mô hình nêu giả định trước khi tạo code:

Dựa trên contract và quy tắc tôi cung cấp, hãy liệt kê unit test cho hàm [tên] bằng [framework]. Trước tiên, nhóm ca hợp lệ, boundary, không hợp lệ và exception. Với từng ca, chỉ rõ quy tắc nào được kiểm tra và expected behavior. Hỏi lại nếu kết quả mong đợi chưa được nêu; không suy ra quy tắc từ code. Sau khi thống nhất danh sách, tạo test theo convention hiện có. Không sửa code production.

Khi nhận mã test, đọc assertion trước rồi chạy test trên repository. Xem test có sử dụng object thật hay mock quá mức; xác nhận tên test phản ánh điều nó thực sự chứng minh. Nếu mô hình đề nghị sửa production code, tách thay đổi đó khỏi test để reviewer hiểu rõ phần nào đang được xác nhận.

Review test do AI sinh

  • Đối chiếu từng assertion với yêu cầu: expected value có căn cứ hay chỉ trùng output hiện tại?
  • Kiểm tra test đỏ khi vi phạm: thử thay đổi logic nhỏ hoặc sửa tạm để biết test có thể bắt lỗi.
  • Đảm bảo test tự cô lập: chạy riêng và trong toàn bộ suite để phát hiện phụ thuộc thứ tự, giờ hệ thống, mạng hoặc dữ liệu cục bộ.
  • Review mock: mock có che logic đang cần kiểm tra không? Nếu test nhiều vào chi tiết nội bộ, refactor có thể làm test vô dụng hoặc giòn.
  • Kiểm tra tên và fixture: tên mô tả hành vi; fixture gọn để người khác đọc hiểu và không chứa dữ liệu nhạy cảm.
  • Chạy lệnh thật: báo chính xác runner và kết quả; test không chạy được không được mô tả là đã xác minh.

Coverage là tín hiệu về dòng/nhánh đã được thực thi trong bộ test, không đo trực tiếp xem assertion có kiểm tra đúng yêu cầu hay không. Một test có thể đi qua mọi dòng mà chỉ khẳng định chương trình không ném lỗi. Vì vậy, dùng coverage để tìm phần chưa chạm tới, rồi đánh giá nội dung và sức bắt lỗi của test bằng review và mutation/thay đổi kiểm tra có kiểm soát nếu nhóm có quy trình.

OWASP Web Security Testing Guide nhấn mạnh cần kiểm tra dữ liệu hợp lệ ở các điểm nhận và chuyển tiếp, không chỉ tin validation ở giao diện. Với unit test, điều này nhắc kỹ sư kiểm tra contract ở đúng tầng và bổ sung integration/security testing ở các handoff có rủi ro; unit test không thay thế toàn bộ kiểm thử hệ thống.

Giới hạn và lỗi thường gặp

  • Test dựa trên code thay vì yêu cầu: mô hình đọc nhánh hiện tại rồi ghi lại giả định mà code đã thực hiện.
  • Assertion quá yếu: chỉ kiểm tra không null, đúng kiểu hoặc gọi hàm thành công.
  • Test trùng lặp: nhiều ca chỉ khác dữ liệu vô nghĩa, làm suite chậm mà không tăng khả năng phát hiện.
  • Mock quá nhiều: test xác nhận mock được gọi nhưng không kiểm tra logic cần thiết.
  • Snapshot thay cho contract: snapshot khổng lồ vỡ vì thay đổi format và khó cho biết hành vi nào quan trọng.
  • Không chạy môi trường thật: tên framework hoặc API được mô hình bịa có thể khiến test không build.

Checklist áp dụng

  1. Viết contract/expected behavior trước khi yêu cầu AI sinh test.
  2. Chuẩn bị ví dụ có nguồn gốc và các ca biên liên quan.
  3. Nêu framework, convention và giới hạn quyền chỉnh sửa.
  4. Yêu cầu AI liệt kê giả định để kỹ sư sửa trước khi tạo code.
  5. Đọc assertion và chạy test; xem riêng, toàn suite và kết quả thật.
  6. Đảm bảo test gắn với hành vi, không phơi bày dữ liệu bí mật.
  7. Review cùng diff thay đổi và bổ sung kiểm thử khác ở ranh giới cần thiết.

Với kiểm tra sản phẩm rộng hơn unit test, xem checklist kiểm thử sản phẩm vibe coding. Khi cần trình bày dự án và cách xác minh chất lượng, tham khảo portfolio kỹ sư phần mềm.

Nguồn tham khảo

AI chỉ hỗ trợ soạn test. Kỹ sư chịu trách nhiệm xác định contract, review test, chạy trong môi trường dự án và xử lý lỗi được phát hiện.

Kỹ sư chạy test ngưỡng phí giao hàng và xem kết quả pull request
Test cần chạy trên repository và bắt đúng điều kiện đã định nghĩa.

Câu hỏi thường gặp

AI có thể thay kỹ sư viết toàn bộ unit test không?

AI có thể tăng tốc bước gợi ý ca và viết boilerplate, nhưng cần người xác nhận expected behavior, assertion và test có chạy trong dự án. Mô hình có thể sao chép hành vi lỗi của code hiện tại hoặc dùng API framework không tồn tại.

Nên cung cấp ngữ cảnh nào cho AI?

Contract, quy tắc nghiệp vụ, ví dụ input/output đã được xác nhận, ca biên, framework và convention. Chỉ đưa phần code cần thiết; bỏ secret, dữ liệu người dùng và tệp không liên quan.

Coverage cao có đồng nghĩa test tốt?

Không. Coverage cho biết code đã được chạy ở mức nhất định nhưng không cho biết assertion có đúng hoặc test có bắt lỗi không. Kiểm tra hành vi được xác minh, trường hợp biên và khả năng test thất bại khi logic sai.

Có nên mock tất cả phụ thuộc?

Không. Mock giúp cô lập đơn vị, nhưng mock quá sâu có thể kiểm tra implementation thay vì hành vi hoặc bỏ sót lỗi tích hợp. Chọn ranh giới cần cô lập; kiểm thử wiring và giao tiếp thật ở lớp phù hợp khác.

Làm sao phát hiện expected value AI tự suy đoán?

Gắn mỗi expected value với yêu cầu, decision record hoặc ví dụ đã duyệt. Nếu không tìm được nguồn, hỏi lại product/owner trước khi chấp nhận. Không coi output hiện tại của hàm là chuẩn đúng chỉ vì nó dễ sao chép vào test.

Cần review gì trong test do AI tạo?

Kiểm tra tên test, điều kiện, assertion, fixture, mock, tính độc lập và runner thực tế. Xem test thất bại khi hành vi bị đổi như dự đoán, không ghi rằng test đã qua nếu chưa chạy trên repository.

ĐĂNG KÝ TƯ VẤN HỌC LẬP TRÌNH TẠI FUNiX

Bình luận (
0
)

Bài liên quan

  • Tầng 0, tòa nhà FPT, 17 Duy Tân, phường Cầu Giấy, Hà Nội
  • info@funix.edu.vn
  • 0782313602 (Zalo, Viber)        

Cơ quan chủ quản: Công ty Cổ phần Giáo dục Trực tuyến FUNiX
MST: 0108171240 do Sở kế hoạch và Đầu tư thành phố Hà Nội cấp ngày 27 tháng 02 năm 2018
Trụ sở chính: Tầng 0, tòa nhà FPT, 17 Duy Tân, phường Cầu Giấy, Hà Nội.

– Văn phòng Hà Nội: Tầng 5 – Toà nhà Diamond 25 Lê Văn Lương, phường Thanh Xuân, Hà Nội.

– Văn phòng TP.HCM: Lầu 3A, tòa nhà 51-53 Võ Văn Tần, phường Xuân Hòa, Thành phố Hồ Chí Minh.

Hotline: 078 231 3602 – Email: info@funix.edu.vn

yêu cầu gọi lại