Giải bài tập SGK: Bài 30: Kiểm thử và gỡ lỗi chương trình – Tin học 10

Mục lục [Ẩn]

Chọn đến phần học sinh cần nhanh chóng thông qua mục lục bằng cách click đến phần đó

Câu hỏi mở đầu

Đề bài: Bài học trước em đã biết khái niệm lỗi ngoại lệ khi chạy chương trình Python. Tuy nhiên, một chương trình chạy không có lỗi ngoại lệ (chương trình không bị dừng) thì không có nghĩa là chương trình không có lỗi. Thậm chí các “lỗi” không tường minh này (các lỗi này được gọi là bug) càng khó phát hiện và khó sửa. Theo em, làm thế nào để kiểm tra (test) và gỡ lỗi (debug) một chương trình? Môi trường lập trình có công cụ nào hỗ trợ việc đó không?

Lời giải:

  • Để kiểm tra (test) chương trình: Chạy thử chương trình với nhiều bộ dữ liệu khác nhau, so sánh kết quả thực tế với kết quả mong đợi. Nếu khác nhau thì chương trình có lỗi.
  • Để gỡ lỗi (debug) chương trình: Tìm xem lỗi nằm ở dòng lệnh nào, vì sao lỗi xảy ra, rồi sửa.
  • Các công cụ hỗ trợ trong môi trường lập trình:
    • Hiển thị mã lỗi ngoại lệ (đã học ở Bài 29).
    • In các giá trị trung gian bằng lệnh print() để kiểm tra.
    • Sử dụng break point (điểm dừng) để dừng chương trình tại một dòng, quan sát giá trị các biến.

→ Bài học này sẽ giới thiệu chi tiết các phương pháp kiểm thử và gỡ lỗi.

1. Một vài phương pháp kiểm thử chương trình

Hoạt động trang 145

Đề bài: Đọc và thảo luận nhóm các phương pháp, công cụ sau để biết chức năng, tác dụng của từng công cụ trong công việc kiểm thử chương trình.

Lời giải:

Tóm tắt 4 phương pháp kiểm thử chương trình trong SGK:

a) Quan sát mã lỗi Runtime và bắt lỗi ngoại lệ

Khi chương trình bị dừng do lỗi ngoại lệ, ta quan sát mã lỗidòng lệnh sinh lỗi để xác định vị trí, từ đó phân tích và sửa lỗi.

b) Kiểm thử chương trình với các bộ dữ liệu test

Chuẩn bị các bộ dữ liệu thử (test) với đầu vào tiêu biểu và đầu ra đã biết trước. Cần chú ý:

  • Nhiều bộ test: đa dạng về độ lớn, tính chất.
  • Bộ test ngẫu nhiên: tăng khả năng phát hiện lỗi.
  • Bộ test ở vùng biên: thường phát sinh lỗi (ví dụ với cặp $(x, y)$ trong miền $0 \leq x, y \leq 1$, các bộ biên là $(0; 0)$, $(0; 1)$, $(1; 0)$, $(1; 1)$).

c) In các thông số trung gian

Bổ sung các lệnh print() vào giữa các dòng lệnh để in ra giá trị các biến trung gian, kiểm tra xem thuật toán có chạy đúng không.

d) Sử dụng công cụ break point (điểm dừng)

Tạo các điểm dừng trong chương trình. Khi chạy, chương trình sẽ dừng lại tại các điểm này để quan sát giá trị của các biến → kiểm tra tính đúng đắn.

Ghi nhớ: Thường kết hợp điểm dừng + in giá trị trung gian sẽ hiệu quả hơn trong kiểm thử chương trình.

Luyện tập trang 148

Luyện tập 1 trang 148

Đề bài: Chương trình của em khi chạy phát sinh lỗi ngoại lệ ZeroDivisionError. Đó là lỗi gì và em sẽ xử lí lỗi này như thế nào?

Lời giải:

Mã lỗi ZeroDivisionError là lỗi xảy ra khi chương trình thực hiện phép chia cho $0$.

Cách xử lí: Trước khi chia, em cần kiểm tra mẫu số xem có bằng $0$ hay không. Nếu bằng $0$ thì không thực hiện phép chia và đưa ra thông báo.

Ví dụ:

m = int(input("Nhập m: "))
n = int(input("Nhập n: "))
if n != 0:
    print("Thương:", m/n)
else:
    print("Không thể chia cho 0!")

→ Bằng cách này, chương trình không bị dừng và người dùng biết lỗi do nhập sai.

Luyện tập 2 trang 148

Đề bài: Chương trình sau có lỗi không? Nếu có thì tìm và sửa lỗi.

m = input("Nhập số tự nhiên m: ")
n = input("Nhập số tự nhiên n: ")
print("Tổng hai số đã nhập là:", m+n)

Lời giải:

Có lỗi (lỗi logic).

Phân tích:

  • Lệnh input() luôn trả về xâu kí tự, không phải số.
  • Sau hai dòng đầu, $m$ và $n$ là xâu kí tự (không phải số).
  • Lệnh m + n sẽ thực hiện phép nối xâu, không phải cộng số.

Ví dụ: Nếu nhập $m = 3$, $n = 5$ thì kết quả in ra là 35 (xâu nối) chứ không phải $8$.

→ Đây là lỗi logic vì chương trình chạy bình thường, không báo lỗi, nhưng kết quả sai.

Cách sửa: Dùng lệnh int() để chuyển xâu thành số nguyên trước khi cộng.

m = int(input("Nhập số tự nhiên m: "))
n = int(input("Nhập số tự nhiên n: "))
print("Tổng hai số đã nhập là:", m+n)

Vận dụng trang 148

Vận dụng 1 trang 148

Đề bài: Chương trình sau có chức năng sắp xếp một dãy số cho trước. Hãy kiểm tra xem chương trình có lỗi không. Nếu có thì tìm và sửa lỗi.

A = [10,1,5,2,8,0,4]
for i in range(len(A)-1):
    j = i
    while j > 1 and A[j] < A[j-1]:
        A[j],A[j-1] = A[j-1],A[j]
        j = j - 1
print(A)

Lời giải:

Có $2$ lỗi logic trong chương trình.

Lỗi 1 – Điều kiện while j > 1:

  • Khi $j = 1$, điều kiện $j > 1$ là sai → vòng while không thực hiện.
  • Nghĩa là không bao giờ so sánh $A[1]$ với $A[0]$.

Sửa: thay j > 1 thành j > 0.

Lỗi 2 – Vòng lặp range(len(A)-1):

  • Với $A$ có $7$ phần tử, range(6) cho $i$ chạy từ $0$ đến $5$.
  • Phần tử cuối $A[6] = 4$ không bao giờ được xét để chèn vào đúng vị trí.

Sửa: thay range(len(A)-1) thành range(len(A)).

Chương trình sau khi sửa:

A = [10,1,5,2,8,0,4]
for i in range(len(A)):
    j = i
    while j > 0 and A[j] < A[j-1]:
        A[j],A[j-1] = A[j-1],A[j]
        j = j - 1
print(A)

Kết quả khi chạy:

[0, 1, 2, 4, 5, 8, 10]

→ Dãy đã được sắp xếp tăng dần. ✓

Chú ý: Em có thể dùng phương pháp in các giá trị trung gian đã học để theo dõi giá trị $A$ sau mỗi vòng lặp, qua đó dễ phát hiện ra lỗi.

Vận dụng 2 trang 148

Đề bài: Để kiểm thử một chương trình, nếu chỉ bằng việc kiểm tra thông qua các bộ dữ liệu test thì có bảo đảm tìm ra hết lỗi của chương trình hay không? Vì sao?

Lời giải:

Không bảo đảm tìm ra hết lỗi chỉ bằng các bộ dữ liệu test.

Lý do:

  • Số lượng bộ test luôn có hạn, không thể bao phủ hết mọi trường hợp đầu vào có thể xảy ra (nhất là với dữ liệu lớn hoặc miền giá trị rộng).
  • Một số lỗi chỉ phát sinh với những bộ dữ liệu đặc biệt mà có thể chưa được test.
  • Chương trình có thể cho kết quả đúng với một số bộ test này nhưng vẫn sai với những bộ test khác chưa thử.

Để giảm thiểu lỗi, cần kết hợp nhiều phương pháp:

  • Dùng bộ test đa dạng: nhiều, ngẫu nhiên, ở vùng biên.
  • In các giá trị trung gian để kiểm tra thuật toán.
  • Dùng công cụ điểm dừng (break point) để theo dõi chương trình.
  • Quan sát mã lỗi khi có lỗi ngoại lệ phát sinh.
Thầy Phạm Thành Danh

Thầy Phạm Thành Danh

(Người kiểm duyệt, ra đề)

Chức vụ: Trưởng ban biên soạn môn Tin Học THPT

Trình độ: Cử nhân Sư phạm Tin học, Chứng chỉ hạng II, Chứng chỉ Tin học, Ngoại ngữ B1

Kinh nghiệm: 8+ năm kinh nghiệm tại Trường THPT Thuận Hóa