Sáu tháng thử nghiệm Agentic Testing: Báo cáo từ môi trường Production
Nút thắt lớn nhất của đội ngũ chúng tôi không phải là việc ra mắt tính năng mới—mà là vòng lặp gây nản lòng khi viết unit test và rà soát lỗi regression. Sáu tháng trước, chúng tôi đã ngừng coi AI như một công cụ autocomplete nâng cao và bắt đầu xây dựng một workflow agentic linh hoạt bằng LangGraph và Pytest. Kết quả mang lại cực kỳ ấn tượng: chúng tôi đã cắt giảm 40% thời gian dành cho boilerplate testing, giúp cả đội tập trung vào kiến trúc hệ thống thay vì các câu lệnh assert.
Hầu hết các lập trình viên coi AI như một “nhà tiên tri” tĩnh: bạn đưa code, nó tạo test, và bạn phải sửa lỗi thủ công khi nó gặp hiện tượng hallucination (ảo giác). Một workflow agentic sẽ khép kín vòng lặp đó. Nó tự viết test, chạy test, phân tích traceback và lặp lại cho đến khi code vượt qua các bài kiểm tra (pass). Toàn bộ quá trình không cần sự can thiệp thủ công.
Thiết lập trong 5 phút: Xây dựng công cụ AI Tester
Bạn chỉ cần Python và một vài thư viện để bắt đầu. Chúng tôi sử dụng LangGraph để điều phối state và Pytest để xử lý việc thực thi. Về phần “bộ não”, bất kỳ mô hình suy luận cao cấp nào như GPT-4o hoặc Claude 3.5 Sonnet đều hoạt động tốt nhất.
pip install langgraph langchain-openai pytest pytest-json-report
Đoạn script tối giản này định nghĩa một state dùng để theo dõi source code, các bản test được tạo và log lỗi:
from typing import TypedDict, List
from langgraph.graph import StateGraph, END
class AgentState(TypedDict):
code: str
tests: str
test_results: str
iterations: int
# Writer: Tạo bộ test suite ban đầu
def coder_node(state: AgentState):
# Yêu cầu LLM viết test dựa trên source code
return {"tests": "def test_logic(): ...", "iterations": state['iterations'] + 1}
# Executor: Chạy test và ghi lại lỗi
def executor_node(state: AgentState):
# Kích hoạt pytest.main() và thu thập kết quả đầu ra
return {"test_results": "failed: AssertionError..."}
# Định nghĩa workflow
workflow = StateGraph(AgentState)
workflow.add_node("writer", coder_node)
workflow.add_node("tester", executor_node)
workflow.set_entry_point("writer")
workflow.add_edge("writer", "tester")
workflow.add_edge("tester", END)
app = workflow.compile()
Vòng lặp tự sửa lỗi: Cách hệ thống tự “chữa lành”
Workflow này thực sự tỏa sáng khi bạn áp dụng conditional routing (điều hướng có điều kiện). Trong thực tế, viết một bản test là chưa đủ; agent phải chứng minh được bản test đó hợp lệ. Tôi đã chia hệ thống của mình thành ba vai trò riêng biệt:
- The Architect: Quét source code để xác định các trường hợp biên (edge cases) quan trọng.
- The Developer: Tạo các file Pytest và các mock cần thiết.
- The Debugger: Phân tích stack trace để sửa logic test hoặc chính source code.
Sử dụng add_conditional_edges, graph sẽ kiểm tra exit code của Pytest. Nếu gặp lỗi “FAIL”, nó sẽ điều hướng state quay lại Debugger. Nếu kết quả là “PASS”, quy trình kết thúc. Đây không chỉ là một script thông thường; nó là một vòng lặp tự sửa lỗi giúp tiết kiệm khoảng 15 giờ làm việc của lập trình viên mỗi tuần.
Mẹo bảo mật: Tạo môi trường Sandbox cho Agent
Ban đầu, tôi nhận ra rằng việc cho phép AI chạy pytest trực tiếp trên máy cục bộ là một cơn ác mộng về bảo mật. Nó có thể vô tình (hoặc theo logic) xóa các file quan trọng. Để giải quyết vấn đề này, chúng tôi đã chuyển việc thực thi sang môi trường Docker. Node của LangGraph sẽ gửi code vào một container tạm thời, chạy test và trả về báo cáo JSON. Cách làm này sạch sẽ, cô lập và an toàn.
Vượt xa những điều cơ bản: Context và Mocking
Code trong thực tế thường rất phức tạp, phụ thuộc vào kết nối Postgres, Redis cache và các API bên thứ ba. Để agent hoạt động hiệu quả, chúng tôi đã triển khai “Context Injection” (Tiêm ngữ cảnh).
Trước khi agent bắt đầu viết code, một node tiền xử lý sẽ trích xuất các fixture trong conftest.py và các signature của hàm. Chúng tôi đưa những thông tin này vào system prompt để AI biết chính xác những mock nào đang có sẵn. Ví dụ, nếu bạn có một fixture db_session, agent nên sử dụng nó thay vì cố gắng khởi tạo một driver database mới.
# Cung cấp ngữ cảnh cho agent
system_msg = f"""
Bạn là Lead QA.
Các fixture hiện có: {active_fixtures}
Ràng buộc: Sử dụng 'unittest.mock' cho tất cả các lệnh gọi bên ngoài.
"""
Việc bổ sung ngữ cảnh này đã giúp giảm 80% các import không tồn tại (hallucinated imports) và cải thiện đáng kể tỷ lệ thành công ngay từ lần chạy đầu tiên.
Những bài học từ thực tế
Nếu bạn đang tích hợp quy trình này vào pipeline CI/CD, hãy ghi nhớ bốn quy tắc sau:
- Giới hạn số lần lặp (Cap the Iterations): Agent có thể bị kẹt trong vòng lặp “sửa-lỗi-sửa”. Chúng tôi giới hạn
AgentStateở mức 5 lần lặp. Nếu sau đó vẫn lỗi, hệ thống sẽ đánh dấu PR để con người can thiệp. - Cấu trúc hóa Log: Đừng bắt LLM phải đọc văn bản thô từ terminal. Hãy sử dụng plugin
pytest-json-reportđể cung cấp dữ liệu có cấu trúc. Việc xử lý dữ liệu này sẽ rẻ hơn và chính xác hơn nhiều đối với mô hình. - Tối thiểu hóa Payload: Gửi một file 2.000 dòng cho mỗi lần sửa test nhỏ là một sự lãng phí token. Chúng tôi sử dụng “Snippet Extractor” để chỉ gửi hàm liên quan và các dòng cụ thể được đánh dấu trong traceback.
- Luôn có sự kiểm soát của con người (Human in the Loop): Chúng tôi sử dụng tính năng
interrupt_beforecủa LangGraph. AI đề xuất cách sửa, nhưng con người phải nhấn “Approve” (Phê duyệt) trước khi merge code.
Workflow agentic không ra đời để thay thế chúng ta. Chúng ở đây để loại bỏ những tác vụ lặp đi lặp lại gây mệt mỏi (burnout). Hệ thống hiện tại của tôi xử lý các công việc nhàm chán ngay cả khi tôi đang ngủ, biến việc viết unit test từ một gánh nặng thành một tiến trình chạy ngầm tự động.

