1. Bối cảnh doanh nghiệp & phạm vi
Một nền tảng EdTech phục vụ luyện thi chứng chỉ nghề (IT, kế toán, ngoại ngữ) tổ chức trung bình 12.000 lượt thi trực tuyến mỗi ngày, riêng mùa cao điểm cuối kỳ có thể lên tới 90.000 lượt trong một tuần. Mỗi kỳ thi có thời lượng cố định (45–180 phút), ngân hàng câu hỏi được rút ngẫu nhiên theo ma trận độ khó, và kết quả ảnh hưởng trực tiếp đến việc cấp chứng chỉ hành nghề — nghĩa là sai sót trong chấm điểm hoặc bỏ lọt gian lận có thể dẫn đến hậu quả pháp lý và uy tín nghiêm trọng. Một nền tảng tương tự từng bị cơ quan chủ quản đình chỉ hợp tác 3 tháng sau khi phát hiện lỗi hệ thống cho phép thí sinh mở hai tab làm bài song song mà không bị phát hiện.
Phạm vi bài viết bao trùm toàn bộ vòng đời một phiên thi: khởi tạo phiên (session), xác thực danh tính, hiển thị đề theo ma trận rút ngẫu nhiên, ghi nhận đáp án theo thời gian thực, giám sát chống gian lận (phát hiện chuyển tab, nhiều thiết bị, camera bị che), nộp bài, chấm điểm tự động theo barem, và hậu kiểm đối soát điểm với barem gốc. Ràng buộc tuân thủ gồm: log giám sát phải lưu tối thiểu 2 năm để phục vụ khiếu nại phúc khảo, và hệ thống chấm điểm phải có khả năng tái tạo (reproducible) — chấm lại cùng một bài nộp ở thời điểm khác phải ra cùng một điểm số.
Phạm vi tự động hoá
- Kiểm thử E2E Playwright cho luồng làm bài, nộp bài, khôi phục phiên
- Kiểm thử API cho engine chấm điểm và đối soát barem
- Kiểm thử kịch bản giám sát: chuyển tab, đa thiết bị, mất kết nối
2. Kiến trúc hệ thống & luồng nghiệp vụ
Kiến trúc gồm 5 thành phần chính: Session Gateway (duy trì kết nối WebSocket theo thời gian thực để phát hiện mất mạng), Exam Engine (quản lý trạng thái đề thi, đồng hồ đếm ngược, thứ tự câu hỏi), Proctoring AI (phân tích luồng camera và sự kiện trình duyệt để phát hiện hành vi bất thường), Answer Store (lưu đáp án theo mô hình append-only để không bao giờ ghi đè mất dữ liệu cũ), và Grading Service (chấm điểm theo barem, hỗ trợ chấm bán tự động cho câu tự luận). Luồng đồng bộ diễn ra liên tục trong suốt bài thi: mỗi lần thí sinh chọn đáp án, client gửi ngay một sự kiện AnswerSaved qua WebSocket, Exam Engine xác nhận và Answer Store ghi bản ghi mới (không sửa bản ghi cũ) để đảm bảo có thể truy vết toàn bộ lịch sử thay đổi đáp án.
Điểm khó khi kiểm thử
Điểm khó nhất là đồng bộ hoá đồng hồ: thời gian còn lại PHẢI được tính trên server, không tin tưởng đồng hồ client, vì client có thể bị chỉnh giờ hệ điều hành hoặc có độ trễ mạng khác nhau — nếu kiểm thử chỉ dựa vào đồng hồ hiển thị trên UI sẽ bỏ lọt lỗi hết giờ nhưng vẫn cho nộp bài. Một khó khăn khác là phân biệt tín hiệu gian lận thật với nhiễu: người dùng vô tình bấm Alt-Tab để xem thông báo hệ thống không nên bị tính như gian lận có chủ đích, nên proctoring cần ngưỡng (ví dụ 3 lần rời tab, mỗi lần trên 5 giây) thay vì cờ nhị phân đơn giản — đây chính là bài toán cân bằng False Positive (báo oan thí sinh trung thực) và False Negative (bỏ lọt gian lận thật). Cuối cùng, việc chấm điểm câu tự luận có AI hỗ trợ cần kiểm thử để đảm bảo điểm AI đề xuất luôn ở trạng thái 'chờ duyệt' cho đến khi giám khảo xác nhận, tránh trường hợp điểm bị khoá tự động sai.
3. Mô hình dữ liệu & bất biến nghiệp vụ (oracle)
Mô hình dữ liệu cốt lõi gồm 5 thực thể: ExamSession (id, studentId, examId, startedAt, deadlineAt, status), QuestionDraw (danh sách câu hỏi đã rút cho phiên này, cố định ngay khi khởi tạo), Answer (append-only, mỗi bản ghi có questionId, value, savedAt, version), Incident (loại vi phạm, mức độ, timestamp, có được xác nhận bởi giám thị hay không), và Score (điểm từng câu, điểm tổng, trạng thái LOCKED/PENDING_REVIEW). Bất biến quan trọng nhất — cũng là oracle chính của toàn bộ bài toán — là: với mọi ExamSession đã SUBMITTED, điểm tổng phải bằng đúng tổng điểm từng câu tính theo barem tại thời điểm chấm, và tập câu trả lời dùng để chấm phải là bản ghi Answer có version mới nhất trước thời điểm nộp bài, không được là bản ghi cũ hơn hoặc bản ghi đến sau deadline.
- Bất biến 1: Điểm = Σ(điểm câu × barem hiện hành), không chấm theo barem cũ nếu đã cập nhật hợp lệ
- Bất biến 2: Mỗi Answer.questionId chỉ có đúng 1 bản ghi 'hiệu lực' tại một thời điểm — bản mới nhất trước deadline
- Bất biến 3: Không tồn tại Answer nào có savedAt sau deadlineAt được dùng để chấm
- Bất biến 4: Mọi Incident mức độ cao (HIGH) phải có ít nhất 1 bằng chứng (ảnh/tab log) đính kèm
- Bất biến 5: Score.status chỉ chuyển LOCKED sau khi mọi câu tự luận đã qua PENDING_REVIEW
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!