Tiết 50, 51
BÀI 30: KIỂM THỬ VÀ GỠ LỖI CHƯƠNG TRÌNH
1. Một vài phương pháp kiểm thử
chương trình
a) Quan sát mã lỗi
Nếu chương trình có lỗi
Runtime (đang chạy bị dừng), quan sát mã lỗi, xác định vị trí sinh ra lỗi.
Từ đó phân tích và tìm cách sửa lỗi.
Ví dụ 1: Xét đoạn chương trình in ra các ước thực sự của
số tự nhiên N (tức là không bao gồm N).
|
Chương trình |
Lỗi / chỉnh sửa |
|
|
1 |
N = input('Nhập vào một số tự
nhiên:') |
Lỗi: input() trả về chuỗi, cần chuyển sang int(). Chỉnh sửa: N = int(input('Nhập vào một số tự nhiên:')) |
|
2 |
for i in range(N): |
Đúng cú pháp:
range(N) tạo dãy từ 0 đến N. Ước số phải lớn hơn 0 và
có thể bằng N. |
|
3 |
if N % i == 0: |
Lỗi: Nếu i=0 sẽ
gây lỗi ZeroDivisionError. Chỉnh sửa: for i in range(1, N): |
|
4 |
print(i, end = ' ') |
Đúng cú pháp: In ra trên một hàng và cách nhau |
b) Kiểm thử chương trình với các bộ dữ liệu kiểm tra (bộ test)
Chương trình cần được
thử với bộ test gồm đầu vào phụ thuộc vào đặc thù của bài toán và đầu ra đã được
biết trước. Cần chú ý những điểm sau:
- Cần có nhiều bộ test: Theo các tiêu chí
như độ lớn, tính đa dạng, ....
- Cần có bộ test ngẫu nhiên: Giúp tăng khả
năng tìm lỗi của chương trình nếu có.
- Cần có bộ test ở vùng biên: Thực tế cho thấy
chương trình thường phát sinh lỗi ở các vùng biên hoặc lân cận của vùng
biên.
Ví dụ 2: Xét chương trình in ra các số không âm trong
danh sách A
|
Chương trình |
Lỗi / chỉnh sửa |
|
|
1 |
def Dem(A): |
(Đúng cú pháp) |
|
2 |
dem = 0 |
(Đúng cú pháp) |
|
3 |
for i in A: |
(Đúng cú pháp) |
|
4 |
if i > 0: |
Lỗi logic: "Số không âm" bao gồm cả số 0. Chỉnh sửa: if i >= 0: |
|
5 |
dem =
dem + 1 |
(Đúng cú pháp) |
|
6 |
return dem |
(Đúng cú pháp) |
|
7 |
||
|
8 |
A = [1, 2, -4, 5, 3, 6] |
(Đúng cú pháp) |
|
9 |
print('SL số không âm là:', Dem(A)) |
(Đúng cú pháp) |
Ví dụ 3: Xét chương
trình tìm ra số lớn nhất trong danh sách A
|
Chương trình |
Lỗi / chỉnh sửa |
|
|
1 |
def TimLonNhat(A): |
(Đúng cú pháp) |
|
2 |
LN = A[0] |
(Đúng logic) |
|
3 |
for i in A: |
Lỗi vùng biên: Khi A = [] |
|
4 |
if i > LN: |
(Đúng logic) |
|
5 |
LN = i |
(Đúng logic) |
|
6 |
return LN |
(Đúng cú pháp) |
|
7 |
||
|
8 |
A = [1, 3, -4, 5, 8, 9] |
(Đúng cú pháp) |
|
9 |
LN = TimLonNhat(A) |
(Đúng cú pháp) |
|
10 |
print('Số lớn nhất trong dãy là:', LN) |
(Đúng cú pháp) |
c) In các thông số
trung gian
- In ra các biến trung gian để kiểm tra các
quy trình hay thuật toán được viết có đúng không.
- Thông qua các giá trị trung gian trong quá
trình thực hiện chương trình, nếu kết quả cuối cùng có lỗi thì dễ tìm ra lỗi
đó.
Ví dụ 4: Xét chương trình tìm và xoá giá trị K có trong
danh sách A
|
Chương trình |
Lỗi / chỉnh sửa |
|
|
1 |
def Xoa(A, K): |
(Đúng cú
pháp) |
|
2 |
for i in range(len(A)): |
Lỗi logic
nghiêm trọng: Vòng lặp for
duyệt theo chỉ số ban đầu, nhưng A.remove() làm thay đổi kích thước và chỉ số của list A ngay trong vòng lặp, dẫn
đến bỏ sót phần tử hoặc lỗi IndexError. |
|
3 |
if A[i] == K: |
(Đúng cú
pháp) |
|
4 |
A.remove(A[i]) |
Lỗi logic: Không nên sửa đổi danh sách khi đang duyệt bằng
chỉ số theo cách này. Giải pháp đề
xuất: Tạo list mới rồi đẩy dữ
liệu qua hoặc dùng vòng lặp while. |
|
5 |
return A |
(Đúng cú
pháp) |
|
6 |
||
|
7 |
A = [1, 2, 3, 1, 1, 3, 2, 1] |
(Đúng cú
pháp) |
|
8 |
K = 1 |
(Đúng cú
pháp) |
|
9 |
print(Xoa(A, Κ)) |
(Đúng cú pháp) |
d) Sử dụng công cụ
break point (điểm dừng)
- Công cụ break point cho phép tạo ra các
"điểm dừng" bên trong chương trình.
- Khi chạy, chương trình sẽ tạm dừng tại các
"điểm dừng" để người kiểm thử có thể quan sát các thông tin bên
trong chương trình, qua đó kiểm tra tính đúng đắn của chương trình.
Ví dụ 5: Chương trình tìm ước chung lớn nhất của hai số
|
Chương trình |
Lỗi / chỉnh sửa |
|
|
1 |
def UCLN(a, b): |
(Đúng cú
pháp) |
|
2 |
while a != b: |
(Đúng logic) |
|
3 |
if a < b: |
(Đúng logic) |
|
4 |
b = b - a |
(Đúng logic) |
|
5 |
else: |
(Đúng cú
pháp) |
|
6 |
a = a - b |
(Đúng logic) |
|
7 |
return a |
(Đúng cú
pháp) |
|
8 |
||
|
9 |
a, b = 25, 125 |
(Đúng cú
pháp) |
|
10 |
x = UCLN(a, b) |
(Đúng cú
pháp) |
|
11 |
print('UCLN của', a, 'và', b, 'là:', x) |
(Đúng cú
pháp) |
Chạy thử chương
trình và tìm ra giá trị a, b ở mỗi lần lặp trong hàm UCLN
(với a=25, b=125)
|
Lần lặp |
Điều kiện (a != b) |
Giá trị a (trước khi thay đổi) |
Giá trị b (trước khi thay đổi) |
Điều kiện (a < b) |
Thay đổi |
Giá trị a (sau) |
Giá trị b (sau) |
|
Đầu (0) |
- |
25 |
125 |
- |
- |
25 |
125 |
|
1 |
True |
25 |
125 |
True |
b = 125 - 25 |
25 |
100 |
|
2 |
True |
25 |
100 |
True |
b = 100 - 25 |
25 |
75 |
|
3 |
True |
25 |
75 |
True |
b = 75 - 25 |
25 |
50 |
|
4 |
True |
25 |
50 |
True |
b = 50 - 25 |
25 |
25 |
|
5 |
False |
25 |
25 |
- |
(Kết thúc lặp) |
25 |
25 |
|
Trả về: |
- |
25 |
- Lưu ý: Trên thực tế phương pháp "điểm dừng"
thường kết hợp với phương pháp in giá trị trung gian để kiểm thử chương
trình được hiệu quả hơn.