Test và đảm bảo chất lượng code tạo bằng AI

Bài test bạn chưa viết

Trong bài học trước, chúng ta đã khám phá việc gỡ lỗi và giải quyết lỗi với AI. Giờ hãy xây dựng trên nền tảng đó. Đây là một tình huống mà mọi nhà phát triển đều từng trải qua: Bạn viết một hàm, kiểm tra thủ công với một vài đầu vào, nó hoạt động, bạn phát hành nó. Ba tuần sau, một người dùng tìm thấy một lỗi. Đầu vào là gì? Một chuỗi rỗng. Hoặc một số âm. Hoặc một danh sách chỉ có một mục thay vì nhiều mục.

Bạn biết mình nên kiểm tra những trường hợp đó. Bạn chỉ... không làm.

AI không quên các trường hợp ngoại lệ. Nó không cảm thấy nhàm chán khi viết bài test thứ 15. Và nó không bỏ qua các đầu vào kỳ lạ vì "điều đó sẽ không bao giờ xảy ra trong môi trường sản xuất." Hãy áp dụng điều đó vào thực tế.

Quy trình kiểm thử AI

Đây là quy trình bạn sẽ sử dụng cho mỗi phiên kiểm thử:

  1. Cung cấp code cần kiểm thử cùng với các dependency của nó
  2. Mô tả hành vi mong muốn (không chỉ những gì code thực hiện — mà là những gì nó nên làm)
  3. Yêu cầu các loại kiểm tra cụ thể (kiểm thử đơn vị, kiểm thử tích hợp, kiểm thử ngoại lệ)
  4. Xem xét và tinh chỉnh các bài test được tạo ra
  5. Thêm các bài test thủ công cho các trường hợp cụ thể mà AI có thể bỏ sót

Hãy cùng xem xét từng bước với một ví dụ thực tế.

Bước 1: Cung cấp cho AI bức tranh toàn cảnh

Giả sử bạn có hàm này:

def calculate_discount(
    subtotal: float,
    coupon_code: str | None,
    is_member: bool,
    items_count: int
) -> dict:
    """Calculate order discount based on multiple factors."""
    discount = 0.0
    reasons = []

    # Member discount: 10%
    if is_member:
        discount += subtotal * 0.10
        reasons.append("Member discount: 10%")

    # Bulk discount: 5% for 10+ items
    if items_count >= 10:
        discount += subtotal * 0.05
        reasons.append("Bulk discount: 5%")

    # Coupon codes
    if coupon_code:
        coupon_discounts = {
            "SAVE20": 0.20,
            "WELCOME10": 0.10,
            "VIP30": 0.30,
        }
        rate = coupon_discounts.get(coupon_code.upper())
        if rate:
            discount += subtotal * rate
            reasons.append(f"Coupon {coupon_code}: {int(rate*100)}%")

    # Cap at 50%
    max_discount = subtotal * 0.50
    if discount > max_discount:
        discount = max_discount
        reasons.append("Capped at 50% maximum")

    return {
        "subtotal": subtotal,
        "discount": round(discount, 2),
        "total": round(subtotal - discount, 2),
        "reasons": reasons,
    }

📍 Nơi dán: Mở ChatGPT (chat.openai.com), Claude (claude.ai) hoặc Gemini (gemini.google.com) và bắt đầu một cuộc trò chuyện mới.

📋 Cách sao chép prompt này: Nhấp vào bất kỳ đâu bên trong khối màu xám, nhấn Cmd+A rồi Cmd+C (Mac) hoặc Ctrl+A rồi Ctrl+C (Windows). Hoặc sử dụng biểu tượng sao chép xuất hiện.

✏️ Cách điền thông tin chi tiết: Thay thế mỗi dấu ngoặc vuông [] và trình giữ chỗ trong ngoặc bằng thông tin cụ thể từ tình huống thực tế của bạn. Thông tin đầu vào mơ hồ sẽ tạo ra kết quả mơ hồ — hãy cụ thể.

👀 Những gì bạn sẽ thấy: Trong vòng vài giây, AI sẽ trả về một phản hồi có cấu trúc dựa vào prompt ở trên. Hãy đọc kỹ và coi đó là bản nháp, không phải câu trả lời cuối cùng.

📌 Cách xử lý kết quả: Lưu phản hồi vào file Notes. Chọn gợi ý có hiệu quả cao nhất và thực hiện nó trong tuần này — đừng cố gắng làm tất cả cùng một lúc.

⚠️ Nếu kết quả không ổn: Nếu các gợi ý có vẻ chung chung, hãy dán nội dung sau: "Hãy cụ thể hơn với ngữ cảnh thực tế của tôi. Bỏ qua những lời khuyên chung chung." Nếu nó bỏ qua các chi tiết quan trọng bạn đã cung cấp, hãy hỏi: "Bạn đã bỏ sót [X] trong ngữ cảnh của tôi — hãy thực hiện lại với điều đó làm ràng buộc chính."

Sau đây là cách bạn hướng dẫn AI:

Viết bộ kiểm thử toàn diện cho hàm calculate_discount này
sử dụng pytest. Bao gồm:

1. Kiểm thử trường hợp bình thường cho từng loại giảm giá
2. Kiểm thử kết hợp (thành viên + phiếu giảm giá, thành viên + mua số lượng lớn, cả ba)
3. Các trường hợp ngoại lệ (tổng phụ bằng không, số âm, phiếu giảm giá dạng chuỗi rỗng,
  phiếu giảm giá không hợp lệ, phân biệt chữ hoa chữ thường)
4. Kiểm thử giới hạn (chính xác 10 mặt hàng, 9 mặt hàng cho ngưỡng mua số lượng lớn)
5. Hành vi khi đạt mức giảm giá tối đa 50%
6. Các trường hợp ngoại lệ về kiểu dữ liệu (Không có so với chuỗi rỗng cho phiếu giảm giá)

Sử dụng tên kiểm thử mô tả rõ ràng tình huống.
Tuân theo mẫu AAA (Arrange, Act, Assert).

[dán hàm ở trên]

Bước 2: Kết quả do AI tạo ra

AI sẽ tạo ra kết quả tương tự như sau (viết tắt):

class TestCalculateDiscount:
    """Tests for the calculate_discount function."""

    # --- Happy Path ---

    def test_member_gets_10_percent_discount(self):
        result = calculate_discount(100.0, None, True, 1)
        assert result["discount"] == 10.0
        assert result["total"] == 90.0
        assert "Member discount: 10%" in result["reasons"]

    def test_bulk_order_gets_5_percent_for_10_plus_items(self):
        result = calculate_discount(200.0, None, False, 10)
        assert result["discount"] == 10.0
        assert "Bulk discount: 5%" in result["reasons"]

    def test_valid_coupon_applies_correct_rate(self):
        result = calculate_discount(100.0, "SAVE20", False, 1)
        assert result["discount"] == 20.0

    # --- Combinations ---

    def test_member_plus_coupon_stacks_discounts(self):
        result = calculate_discount(100.0, "SAVE20", True, 1)
        assert result["discount"] == 30.0  # 10% + 20%

    def test_all_discounts_combined_hits_cap(self):
        result = calculate_discount(100.0, "VIP30", True, 15)
        assert result["discount"] == 50.0  # 10+5+30=45... wait
        # Actually 10% + 5% + 30% = 45%, under 50% cap
        assert result["discount"] == 45.0

    # --- Edge Cases ---

    def test_zero_subtotal_returns_zero_discount(self):
        result = calculate_discount(0.0, "SAVE20", True, 10)
        assert result["discount"] == 0.0
        assert result["total"] == 0.0

    def test_invalid_coupon_code_ignored(self):
        result = calculate_discount(100.0, "BOGUS", False, 1)
        assert result["discount"] == 0.0

    def test_coupon_case_insensitive(self):
        result = calculate_discount(100.0, "save20", False, 1)
        assert result["discount"] == 20.0

    def test_empty_string_coupon_treated_as_no_coupon(self):
        result = calculate_discount(100.0, "", False, 1)
        assert result["discount"] == 0.0

Bạn có nhận thấy điều gì thú vị không? AI đã phát hiện ra một lỗi tiềm ẩn trong chính bài test của nó - trường hợp "tất cả các khoản giảm giá được kết hợp". Ban đầu, nó dự đoán mức giảm giá là 50% (đã giới hạn), sau đó tính toán lại và nhận ra rằng 45% thực tế thấp hơn mức giới hạn. Kiểu tư duy có hệ thống này chính là điểm mạnh của các bài test AI.

Bước 3: Xem lại các bài test được tạo ra

Đừng tin tưởng một cách mù quáng vào các bài test do AI tạo ra. Hãy kiểm tra những vấn đề sau:

Các bài test trùng lặp chỉ kiểm tra xem code có thực hiện đúng chức năng của nó hay không, mà không kiểm tra xem code có thực hiện đúng chức năng đó hay không:

# BAD: This just re-implements the function logic
def test_discount_calculation(self):
    subtotal = 100.0
    expected = subtotal * 0.10  # Just copying the source logic
    result = calculate_discount(subtotal, None, True, 1)
    assert result["discount"] == expected

Những trường hợp ngoại lệ mà AI có thể chưa nghĩ đến:

# Did AI test these?
def test_negative_subtotal(self):
    # Should this even be allowed? What's the expected behavior?
    result = calculate_discount(-50.0, None, True, 1)
    # This reveals a design question, not just a bug

def test_floating_point_precision(self):
    result = calculate_discount(33.33, "SAVE20", True, 1)
    # 33.33 * 0.30 = 9.999... Does rounding work correctly?
    assert result["discount"] == 10.0  # or 9.99?

Những khẳng định sai lầm khi giá trị mà AI kỳ vọng không chính xác. Hãy chạy mọi bài test và xác minh rằng các lỗi thực sự là do lỗi phần mềm, chứ không phải do kỳ vọng sai.

Kiểm tra nhanh: Tìm ra vấn đề

Đây là một bài test do AI tạo ra. Có gì sai với nó?

def test_discount_applied(self):
    result = calculate_discount(100.0, "SAVE20", False, 1)
    assert result is not None
    assert "discount" in result
    assert "total" in result

Vấn đề: Bài test này chỉ kiểm tra xem hàm có trả về giá trị nào đó hay không, chứ không kiểm tra xem các giá trị đó có chính xác hay không. Bài test này sẽ vẫn vượt qua ngay cả khi phép tính giảm giá hoàn toàn sai. Luôn luôn kiểm tra các giá trị cụ thể.

Tạo bài test tích hợp

Bài test đơn vị bao gồm các hàm riêng lẻ. Bài test tích hợp bao gồm cách các thành phần hoạt động cùng nhau. AI rất giỏi trong việc tạo cả hai – bạn chỉ cần cung cấp thêm ngữ cảnh:

Viết bài test tích hợp cho quy trình thanh toán đơn hàng của chúng ta.
Đây là cách các thành phần kết nối:

1. CartService.getItems() trả về các mặt hàng trong giỏ hàng
2. DiscountService.calculate() áp dụng giảm giá
3. PaymentService.charge() xử lý thanh toán
4. OrderService.create() tạo bản ghi đơn hàng

Kiểm tra các trường hợp sau:
- Thanh toán thành công với giảm giá
- Thanh toán thất bại không nên tạo đơn hàng
- Giỏ hàng trống nên bị từ chối sớm
- Mã giảm giá hết hạn trong quá trình thanh toán

Đây là giao diện của mỗi dịch vụ:
[dán các giao diện liên quan]

Sử dụng pytest với unittest.mock để mô phỏng dịch vụ.

AI tạo ra các bài test xác minh sự tương tác giữa những dịch vụ - đảm bảo rằng các phương thức phù hợp được gọi theo đúng thứ tự với những tham số chính xác, và lỗi ở một bước sẽ ngăn chặn các bước tiếp theo.

Kim tự tháp test với AI

AI thay đổi cách bạn tiếp cận kim tự tháp test:

        /\
       /  \  Kiểm thử E2E
      /    \  (AI giúp viết, bạn thiết kế các tình huống)
     /------\
    /        \  Kiểm thử tích hợp
   /          \  (AI được tạo ra từ giao diện dịch vụ)
  /------------\
 /              \  Kiểm thử đơn vị
/                \  (AI tạo ra hầu hết những thứ này cho bạn)
------------------

Kiểm thử đơn vị: Hãy để AI tạo ra hơn 80% các bài test này. Các trường hợp ngoại lệ mà AI phát hiện ra vô cùng quý giá. Xem xét và bổ sung thêm các trường hợp cụ thể theo từng lĩnh vực.

Kiểm thử tích hợp: Cùng tạo với AI. Bạn định nghĩa các kịch bản và tương tác; AI viết code kiểm thử và thiết lập mô phỏng.

Kiểm thử đầu cuối (E2E): Bạn thiết kế luồng người dùng; AI giúp chuyển đổi chúng thành code kiểm thử (Playwright, Cypress, v.v.).

Yêu cầu AI tìm ra những gì CHƯA được kiểm thử

Một trong những gợi ý kiểm thử mạnh mẽ nhất:

Đây là hàm của tôi và bộ kiểm thử hiện tại của nó.
Những hành vi, trường hợp ngoại lệ hoặc điều kiện lỗi nào
hiện CHƯA được kiểm thử?

[dán hàm]
[dán các bài test hiện có]

AI sẽ xác định các lỗ hổng như:

  • "Không có bài test khi items_count bằng 0"
  • "Không có bài test xác minh thứ tự mảng lý do" 
  • "Không có bài test cho các phép tính chiết khấu đồng thời"
  • "Không có bài test cho các tổng phụ cực lớn (tràn?)"

Điều này giống như việc có một kỹ sư QA cấp cao xem xét phạm vi kiểm thử của bạn.

Bài tập thực hành

Hãy lấy một hàm bạn vừa viết gần đây và thử quy trình làm việc này:

  1. Dán nó vào trợ lý AI của bạn
  2. Yêu cầu kiểm thử toàn diện bao gồm cả các trường hợp ngoại lệ
  3. Xem xét mọi bài test được tạo ra — chúng kiểm thử hành vi hay chỉ kiểm thử triển khai?
  4. Chạy các bài test — tất cả có đạt không? Nếu không, đó là lỗi trong code hay trong bài test?
  5. Hỏi AI: "Những gì CHƯA được kiểm thử?" và thêm các trường hợp đó

Bạn có thể sẽ phát hiện ra ít nhất một trường hợp ngoại lệ mà bạn chưa xem xét.

Những điểm chính cần ghi nhớ

  • AI rất giỏi trong việc xác định các trường hợp ngoại lệ và điều kiện biên mà con người bỏ sót
  • Cung cấp hàm, các dependency của nó và hành vi mong đợi để có kết quả tốt nhất
  • Xem xét các bài test được tạo ra để tìm những khẳng định trùng lặp và giá trị mong đợi sai
  • Sử dụng AI để tìm ra các lỗ hổng trong phạm vi kiểm thử hiện có
  • Hãy để AI xử lý phần lớn các bài test đơn vị; cùng tạo những bài test tích hợp và kiểm thử đầu cuối
  • Luôn chạy các bài test được tạo ra và xác minh rằng bạn có thể thấy các lỗi thực sự
  • Câu 1:

    Đối với một hàm chấp nhận một danh sách, các bài kiểm tra do AI tạo ra nên bao phủ những trường hợp ngoại lệ nào?

    GIẢI THÍCH:

    Các điều kiện biên cho đầu vào danh sách bao gồm: Trống, một phần tử duy nhất, danh sách lớn, đầu vào null/không xác định, trùng lặp và các mục có kiểu không mong đợi. Việc bao phủ toàn diện các trường hợp ngoại lệ là nơi những bài kiểm tra do AI tạo ra thực sự tỏa sáng.

  • Câu 2:

    Bạn nên làm gì với các bài test do AI tạo ra trước khi tin tưởng chúng?

    GIẢI THÍCH:

    Các bài test do AI tạo ra đôi khi kiểm tra những chi tiết triển khai hơn là hành vi. Một bài test chỉ xác nhận code hoạt động như mong đợi là vô dụng — hãy xác minh rằng các bài test kiểm tra những hành vi có ý nghĩa và sẽ phát hiện ra các lỗi thực sự.

  • Câu 3:

    Khi tạo bài test bằng AI, bạn nên cung cấp:

    GIẢI THÍCH:

    Càng nhiều ngữ cảnh mà AI có — code, các dependency của nó, những hành vi dự kiến ​​và các trường hợp ngoại lệ đã biết — thì những bài test mà nó tạo ra càng tốt. Ngữ cảnh một phần dẫn đến các bài test không đầy đủ hoặc không chính xác.

  • Câu 4:

    Ưu điểm lớn nhất của việc sử dụng AI để tạo bài test là gì?

    GIẢI THÍCH:

    Mặc dù AI cũng nhanh hơn, nhưng sức mạnh thực sự của nó là khả năng suy nghĩ một cách có hệ thống về các trường hợp ngoại lệ — đầu vào trống, giá trị biên, truy cập đồng thời, trạng thái không hợp lệ — mà các nhà phát triển con người thường bỏ sót.

Thứ Tư, 10/06/2026 11:38
51 👨
Xác thực tài khoản!

Theo Nghị định 147/2024/ND-CP, bạn cần xác thực tài khoản trước khi sử dụng tính năng này. Chúng tôi sẽ gửi mã xác thực qua SMS hoặc Zalo tới số điện thoại mà bạn nhập dưới đây:

Số điện thoại chưa đúng định dạng!
Số điện thoại này đã được xác thực!
Bạn có thể dùng Sđt này đăng nhập tại đây!
Lỗi gửi SMS, liên hệ Admin
0 Bình luận
Sắp xếp theo