1.1. Lỗi trong chương trình và kiểm thử
– Gỡ lỗi: là quá trình xác định lỗi và sửa lỗi.
– Khi lập trình thường gặp các lỗi sau:
+ Lỗi cú pháp: là lỗi câu lệnh viết không theo đúng quy định của ngôn ngữ.
+ Lỗi ngoại lệ: (Exceptions Error) còn gọi là lỗi Runtime, là lỗi xảy ra khi chương trình đang chạy, một lệnh nào đó không thể thực hiện được
+ Lỗi ngữ nghĩa (lỗi logic): là lỗi mặc dù các câu lệnh viết đúng quy định của ngôn ngữ nhưng sai thao tác xử lí nào đó. Đây là loại lỗi rất khó phát hiện.
– Ví dụ:
+ Xét chương trình ở Hình 1a, chương trình này thực hiện yêu cầu nhập vào hai số nguyên p, q và danh sách a gồm các số nguyên, sau đó đưa ra max{│ai│, i = p, p + 1, …, q}. Biết rằng các phần tử của danh sách a được đánh chỉ số bắt đầu từ 0 và 0 ≤ p ≤ q < len(a)
Hình 1a. Chương trình cần kiểm thử và tìm lỗi |
|
Hình 1b. Kết quả đúng |
Hình 1c. Kết quả sai |
+ Giải thích:
. Với đầu vào p = 1, q = 4 (Hình 1b), dãy con được xét là 7 1 5 -6, nên 7 là đáp án đúng, là số có giá trị tuyệt đối lớn nhất trong dãy con đó
. Với đầu vào p = 2, q = 4 (Hình 1c), dãy con được xét là 1 5 -6, đáp án đúng phải là 6
– Việc đọc kĩ lại chương trình để tìm lỗi chỉ thích hợp với các chương trình ngắn, đơn giản
– Môi trường lập trình của những ngôn ngữ lập trình bậc cao có công cụ hỗ trợ cho người dùng tìm lỗi
– Các lỗi ngữ nghĩa chỉ có thể phát hiện thông qua quan sát kết quả thực hiện chương trình với các bộ dữ liệu vào (các bộ test) khác nhau
– Để kiểm tra tính đúng đắn của chương trình so với yêu cầu của đề bài, trước hết cần chuẩn bị các bộ dữ liệu vào. Dữ liệu kiểm thử phải phù hợp với các ràng buộc đã cho và chia thành 3 nhóm:
+ Kiểm thử những trường hợp thường gặp trong thực tế
+ Kiểm thử những trường hợp đặc biệt (ví dụ, khi danh sách chỉ bao gồm một phần tử)
+ Kiểm thử những trường hợp các tham số nhận giá trị lớn nhất có thể
1.2. Truy vết với cách bổ sung câu lệnh theo dõi kết quả trung gian
– Cách tìm lỗi ngữ nghĩa:
+ Bổ sung vào chương trình những câu lệnh đưa ra các kết quả trung gian nhằm truy vết các xử lí của chương trình. => dự đoán và khoanh vùng được phần chương trình chứa các câu lệnh đưa đến kết quả sai và sửa lại
Chú ý: Sau khi sửa xong chương trình cần xóa đi các câu lệnh đã thêm vào để truy vết hoặc biến chúng thành chú thích
– Ví dụ: Xét lại ví dụ ở mục 1.1
Hình 2a. Chương trình ở Hình 1a đã thêm câu lệnh để truy vết |
|
Hình 2a. Kết quả đúng |
Hình 2a. Kết quả sai |
=> Ta thấy lỗi ở việc xác định miền tìm max và cần phải sửa lại câu lệnh for i in range(p,q): thành for i in range(p,q+1):
– Dựa vào ví dụ, ta thấy cách truy vết này phải can thiệp vào chương trình nguồn, thêm các câu lệnh mới và sau đó phải xóa các câu lệnh truy vết không còn cần thiết.
=> Nhược điểm: Bất tiện vì câu lệnh mới đưa vào có thể có lỗi hoặc đưa nhầm vào vị trí không thích hợp.
1.3. Truy vết với công cụ gỡ lỗi của ngôn ngữ lập trình
Để kích hoạt chế độ gỡ lỗi (Debug), ta thực hiện lần lượt các thao tác sau:
– Mở file chương trình cần gỡ lỗi
– Chọn Debug => chọn Debugger (Hình 3) => xuất hiện cửa sổ Debug Control (Hình 4)
– Chọn Run Module (Hoặc F5)
– Chọn Step (hoặc Over)
* Kết luận:
– Để tìm và sửa lỗi ngữ nghĩa cần dùng biện pháp truy vết
– Muốn truy vết để tìm lỗi:
+ Có thể đưa thêm các câu lệnh xuất ra kết quả trung gian của quá trình tính toán
+ Có thể sử dụng công cụ gỡ lỗi của môi trường lập trình
⇒ Truy vết để tìm lỗi là một quá trình khá khó khăn và phức tạp, đôi khi mất khá nhiều thời gian
⇒ Python còn trang bị một thư viện riêng cung cấp các dịch vụ gỡ lỗi, đó là thư viện PDB
1.4. Thực hành gỡ lỗi cho chương trình
Xét bài toán: Cho a là danh sách các số nguyên. Em hãy tạo danh sách b có các phần tử ở vị trí lẻ bằng phần tử ở vị trí tương ứng của a, các phần tử ở vị trí chẵn bằng phần tử ở vị trí tương ứng của a cộng thêm 1, tức là:
\({b_i} = \left\{ \begin{array}{l}
{a_i} + 1,i = 0,2,4,…\\
{a_i},i = 1,3,5,…
\end{array} \right.\)
– So sánh số lượng các phần tử từ giá trị chẵn ở a với số lượng các phần tử giá trị chẵn ở b, đưa ra thông báo.
– Gọi p là số lượng các phần tử giá trị chẵn ở a, q là số lượng các phần tử giá trị chẵn ở b và đưa ra thông báo “a ít hơn” nếu p < q, “b ít hơn” nếu p > q và “Bằng nhau” trong trường hợp còn lại
Nhiệm vụ: Áp dụng truy vết để xác định lỗi và đề xuất cách sửa một số ít nhất các câu lệnh để có chương trình đúng
Hình 6. Chương trình cần được gỡ lỗi
Hướng dẫn:
– Phương pháp dùng công cụ Gỡ lỗi (Debug)
+ Chuẩn bị danh sách số nguyên, ví dụ [5, 3, 2, 2, 1, 2]
+ Chọn Debugger, chọn Step, quan sát giá trị hai danh sách a và b. Sau một vài lần thực hiện câu lệnh trong vòng lặp:
for i in range(0,n,2):
b[i] = b[i] + 1
Ta thấy: a và b đồng thời thay đổi giá trị, mặc dù trong vòng lặp chỉ chứa câu lệnh thay đổi giá trị của danh sách b.
– Ví dụ:
– Sau khi i = 2 ta có kết quả như Hình 7
⇒ Chương trình chưa tạo ra bản sao của danh sách a mà chỉ tạo một tên mới cho cùng một danh sách a
⇒ Câu lệnh sai trong chương trình là b = a
⇒ sửa là: b = [] + a
Hình 7. Minh họa kết quả của phương pháp gỡ lỗi
– Phương pháp bổ sung vào chương trình các câu lệnh truy vết
+ Thêm câu lệnh print(a) và print(b) để xuất ra giá trị các danh sách a và b sau mỗi vòng lặp
⇒ Dễ dàng nhận thấy a và b cùng đồng thời thay đổi
⇒ Kết luận: Câu lệnh sai trong chương trình là b = a
⇒ sửa là: b = [] + a
– Có ba loại bộ dữ liệu vào cần tạo để kiềm tra, đánh giá chương trình. – Lỗi ngữ nghĩa khó phát hiện. – Để tìm và sừa lỗi ngữ nghĩa cần dùng biện pháp truy vết – Muốn truy vết để tìm lỗi: + Có thể đưa thêm các câu lệnh xuất ra kết quả trung gian của quá trinh tính toán. + Có thể sử dụng công cụ gỡ lỗi của môi trường lập trình. – Trên cửa sổ Debug Control có phần hiển thị thông tin về giá trị các biến trong chương trình. |
---|