Kiểm thử phần mềm
Kiểm thử biến hình cho bộ kiểm chứng thời khóa biểu
Suy luận về phép hoán vị, đổi mã và nới ràng buộc. Tạo ca neo và phản ví dụ để phát hiện lỗi phụ thuộc dữ liệu.
Thích và đánh giá Bình luận và hỏi đáp1. Khi biết quy luật nhưng khó tính kết quả đầy đủ
Với một thời khóa biểu lớn, ta có thể biết lịch cần tránh trùng phòng và trùng giảng viên, nhưng khó liệt kê thủ công số lỗi và từng khoản phạt. Trong kiểm thử, đây là một dạng khó khăn về oracle, tức nguồn xác định kết quả mong đợi. Kiểm thử biến hình khai thác các quan hệ giữa nhiều lần chạy. Ta biến đổi dữ liệu theo một quy tắc và kiểm tra xem kết quả mới có quan hệ đúng với kết quả cũ hay không.
Ví dụ, đổi thứ tự các bản ghi trong tệp lịch không làm thay đổi việc hai buổi có trùng ca hay trùng phòng. Ta chưa cần biết trước lịch lớn có bao nhiêu lỗi, nhưng có thể kiểm tra rằng các số đếm không đổi sau khi hoán vị. Nếu bộ kiểm chứng dựa nhầm vào vị trí các dòng thay vì khóa nghiệp vụ, phép thử này có thể làm lộ lỗi.
2. Đặt tiền điều kiện cho mỗi quan hệ biến hình
| Phép biến đổi | Tiền điều kiện | Kỳ vọng |
|---|---|---|
| Hoán vị bản ghi | Giữ nguyên tập buổi và mọi trường. | Số lỗi và điểm giữ nguyên. |
| Đổi mã bằng song ánh | Đổi nhất quán trong lịch, ràng buộc và bảng ưu tiên. | Số lỗi và điểm giữ nguyên. |
| Nới một ràng buộc cứng | Giữ các ràng buộc còn lại và hàm mục tiêu. | Mọi lịch từng hợp lệ vẫn hợp lệ. |
Điều kiện đổi mã nhất quán rất quan trọng. Nếu đổi mã GV A thành x_A trong lịch mà bảng ưu tiên vẫn dùng A, điểm mềm có thể thay đổi. Đây là phản ví dụ cho một quan hệ viết thiếu tiền điều kiện. Tương tự, khi nới ràng buộc cứng, điểm tối ưu chỉ được bảo đảm không tăng nếu đang tối thiểu hóa cùng một hàm mục tiêu và cả hai giá trị là tối ưu thật sự. Kết quả tốt nhất tìm thấy trong một thời hạn cố định có thể không tuân theo thứ tự đó.
3. Kết hợp ca neo với các phép biến đổi
Môi trường thực hành. Python 3.10 trở lên. Ví dụ dùng thư viện chuẩn Python.
"""Kiểm thử biến hình cho bộ kiểm chứng lịch đồ chơi."""
from dataclasses import dataclass, replace
from itertools import combinations, permutations
@dataclass(frozen=True)
class Buoi:
ma: str
phong: str
gv: str
ca: int
thu: int
def danh_gia(lich, gv_uu_tien):
trung_phong = sum(a.ca == b.ca and a.thu == b.thu and a.phong == b.phong
for a, b in combinations(lich, 2))
trung_gv = sum(a.ca == b.ca and a.thu == b.thu and a.gv == b.gv
for a, b in combinations(lich, 2))
if trung_phong or trung_gv:
return (trung_phong, trung_gv, None)
ngay = {b.thu for b in lich if b.gv == gv_uu_tien}
return (0, 0, 5 * {2, 6}.issubset(ngay))
if __name__ == "__main__":
sample = [
Buoi("L1", "P101", "A", 1, 2),
Buoi("L2", "P102", "B", 1, 2),
Buoi("L3", "P101", "A", 1, 6),
]
conflict = [sample[0], replace(sample[1], phong="P101", gv="A"), sample[2]]
# Neo kỳ vọng để tránh một validator luôn trả cùng một kết quả.
assert danh_gia(sample, "A") == (0, 0, 5)
assert danh_gia(conflict, "A") == (1, 1, None)
for lich in (sample, conflict):
expected = danh_gia(lich, "A")
for permutation in permutations(lich):
assert danh_gia(permutation, "A") == expected
renamed = [replace(b, ma="x_" + b.ma, phong="x_" + b.phong, gv="x_" + b.gv)
for b in lich]
assert danh_gia(renamed, "x_A") == expected
# Minh họa lỗi thiết kế test: đổi ID giảng viên mà quên đổi ưu tiên.
renamed = [replace(b, gv="x_" + b.gv) for b in sample]
assert danh_gia(renamed, "A") == (0, 0, 0)
print("Đạt kiểm thử hoán vị và đổi mã đồng bộ trên hai lịch.")Chạy python kiem_thu_bien_hinh.py. Ví dụ có một lịch khả thi nhận 5 điểm và một lịch gây đúng một lỗi phòng, một lỗi giảng viên. Hai kỳ vọng cụ thể đóng vai trò ca neo. Sau đó, chương trình thử các hoán vị và đổi mã đồng bộ. Bộ kiểm chứng luôn trả một số cố định có thể vượt qua phép thử bất biến, nhưng sẽ thất bại trên một trong hai ca neo.
Chương trình so sánh số lỗi và điểm, vì đó là hợp đồng của hàm. Nếu hệ thống thực trả danh sách vi phạm, cần quyết định thứ tự có phải là một phần của hợp đồng hay không. Nếu thứ tự không quan trọng, so sánh các bản ghi lỗi đã chuẩn hóa theo cặp lớp và mã ràng buộc. Khi đổi mã, áp dụng phép ánh xạ ngược trước khi so thông báo gốc.
4. Dùng phản ví dụ để cải thiện bộ kiểm thử
Thử sửa vòng kiểm tra để chỉ so hai buổi đứng kề trong danh sách. Tạo lịch với hai buổi trùng bị ngăn cách bởi một buổi khác, rồi hoán vị để đưa chúng sát nhau. Hai kết quả khác nhau cho thấy cách kiểm tra phụ thuộc thứ tự. Tiếp theo, thử bổ sung trường cơ sở hoặc nhóm sinh viên. Viết rõ phép đổi mã nào hợp lệ trước khi sinh thêm ca tự động.
Khi báo cáo, hãy ghi số quan hệ đã dùng, các miền dữ liệu, số lỗi chủ động đưa vào mà bộ thử phát hiện, và phản ví dụ nhỏ nhất tìm được. Phương pháp này bổ sung cho đối chiếu bằng lịch nhỏ, kiểm tra biên và so sánh với bộ kiểm chứng độc lập. Đọc thêm tại Chen và cộng sự · Tổng quan kiểm thử biến hình.