Kiểm thử và tích hợp
Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 104 trên 107.
Thử thách
DễHãy hoàn thiện Hệ thống quản lý thư viện bằng cách viết các bài kiểm tra để xác nhận mọi thứ hoạt động chính xác! Bạn sẽ tạo một tệp kiểm tra để xác thực các chức năng cốt lõi của thư viện: đảm bảo sách có thể được mượn và trả đúng cách, đồng thời các trường hợp lỗi được xử lý chính xác.
Bạn sẽ sắp xếp code trong năm tệp:
book.go: StructBookvới các trườngID,Title,Author,ISBNvàAvailable. Thêm hàm khởi tạoNewBookđể khởi tạo sách ở trạng thái có sẵn.user.go: StructUservới các trườngID,Name,EmailvàBorrowedBooks. Thêm hàm khởi tạoNewUser.library.go: StructLibraryvới các map lưu sách và người dùng, cùng các phương thứcNewLibrary,AddBook,AddUser,BorrowvàReturn. Phương thứcBorrowcần trả về lỗi nếu người dùng không hợp lệ, sách không hợp lệ hoặc sách không có sẵn. Phương thứcReturncần trả về lỗi nếu người dùng không hợp lệ, sách không hợp lệ hoặc sách chưa được mượn.library_test.go: Đây là nơi bạn viết các hàm kiểm tra! Tạo các bài kiểm tra để xác nhận:TestBorrowSuccess: Xác nhận việc mượn một cuốn sách có sẵn thành công, không trả về lỗi, sách chuyển sang trạng thái không có sẵn và mã sách được thêm vào danh sách sách đã mượn của người dùngTestBorrowUnavailable: Xác nhận việc mượn một cuốn sách đã được mượn sẽ trả về lỗiTestBorrowInvalidUser: Xác nhận việc mượn sách bằng mã người dùng không tồn tại sẽ trả về lỗiTestReturnSuccess: Xác nhận việc trả một cuốn sách đã mượn thành công, sách lại trở nên có sẵn và mã sách được xóa khỏi danh sách sách đã mượn của người dùng
Mỗi bài kiểm tra cần tự thiết lập thư viện cùng những cuốn sách và người dùng cần thiết, thực hiện thao tác rồi kiểm tra kết quả bằng
t.Errorhoặct.Errorfkhi xác nhận không đạt.main.go: Chạy thủ công các bài kiểm tra và báo cáo kết quả. Đọc tên bài kiểm tra cần chạy (borrow_success,borrow_unavailable,borrow_invalid_userhoặcreturn_success). Dựa trên tên bài kiểm tra, thiết lập tình huống tương ứng và in raPASSnếu mọi xác nhận đều đạt, hoặcFAIL: [reason]nếu có xác nhận nào không đạt.
Đầu vào sẽ có dạng sau:
- Tên bài kiểm tra:
borrow_success,borrow_unavailable,borrow_invalid_userhoặcreturn_success
Với mỗi bài kiểm tra, hãy dùng dữ liệu kiểm tra tiêu chuẩn sau:
- Sách: mã
B001, tiêu đềGo Programming, tác giảJohn Doe, ISBN123-456 - Người dùng: mã
U001, tênAlice, emailalice@test.com
Ví dụ, với đầu vào:
borrow_successĐầu ra cần là:
PASSVới đầu vào:
borrow_unavailableĐầu ra cần là:
PASSVới đầu vào:
borrow_invalid_userĐầu ra cần là:
PASSVới đầu vào:
return_successĐầu ra cần là:
PASSVới borrow_success: Tạo thư viện, thêm sách và người dùng, mượn sách, xác nhận không có lỗi, xác nhận sách không còn có sẵn và xác nhận sách nằm trong danh sách sách đã mượn của người dùng.
Với borrow_unavailable: Tạo thư viện, thêm sách và người dùng, đặt Available của sách thành false, thử mượn sách rồi xác nhận có lỗi được trả về.
Với borrow_invalid_user: Tạo thư viện, chỉ thêm sách mà không thêm người dùng, thử mượn sách bằng mã người dùng U001 rồi xác nhận có lỗi được trả về.
Với return_success: Tạo thư viện, thêm sách và người dùng, mượn sách trước rồi trả lại, xác nhận không có lỗi, sách lại có sẵn và danh sách sách đã mượn của người dùng trống.
Viết bài kiểm tra giúp đảm bảo hệ thống thư viện hoạt động chính xác và giúp bạn tự tin thay đổi code mà không làm hỏng các chức năng hiện có!
Tự làm thử
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
testName, _ := reader.ReadString('\n')
testName = strings.TrimSpace(testName)
// Dữ liệu mẫu chuẩn cho kiểm thử
// Sách: ID "B001", tiêu đề "Go Programming", tác giả "John Doe", ISBN "123-456"
// Người dùng: ID "U001", tên "Alice", email "alice@test.com"
switch testName {
case "borrow_success":
// TODO: Kiểm tra việc mượn sách còn sẵn có thành công
// 1. Tạo thư viện, thêm sách và người dùng
// 2. Mượn sách
// 3. Kiểm tra: không có lỗi, sách không còn sẵn, người dùng có sách trong danh sách
// In ra "PASS" nếu tất cả đều đạt, hoặc "FAIL: [reason]" nếu có trường hợp không đạt
fmt.Println("FAIL: not implemented")
case "borrow_unavailable":
// TODO: Kiểm tra việc mượn sách không còn sẵn trả về lỗi
// 1. Tạo thư viện, thêm sách và người dùng
// 2. Đặt Available của sách thành false
// 3. Thử mượn sách
// 4. Kiểm tra có lỗi trả về
fmt.Println("FAIL: not implemented")
case "borrow_invalid_user":
// TODO: Kiểm tra việc mượn sách bằng người dùng không hợp lệ có trả về lỗi hay không
// 1. Tạo thư viện, chỉ thêm sách (không thêm người dùng)
// 2. Thử mượn sách bằng ID người dùng "U001"
// 3. Kiểm tra xem có trả về lỗi hay không
fmt.Println("FAIL: not implemented")
case "return_success":
// TODO: Kiểm tra việc trả sách đã mượn có thành công hay không
// 1. Tạo thư viện, thêm sách và người dùng
// 2. Mượn sách trước
// 3. Trả sách
// 4. Kiểm tra: không có lỗi, sách có thể mượn, danh sách sách đã mượn của người dùng trống
fmt.Println("FAIL: not implemented")
default:
fmt.Println("FAIL: unknown test")
}
}
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng OOP trong Go
Tệp bên ngoàiWorkspace và module trong GoPackage và importTên được export và không được exportGiới thiệu về OOP trong GoStruct như lớpĐịnh nghĩa phương thức cho structReceiver kiểu con trỏ và kiểu giá trịKhởi tạo structHàm khởi tạoÔn tập: máy tính đơn giản4Interface
Giới thiệu về interfaceTriển khai ngầm địnhInterface như một hợp đồngInterface rỗng (any)Khẳng định kiểuswitch kiểuKết hợp interfaceInterface Stringer và ErrorÔn tập: Máy tính hình học7Tính đóng gói
Trường được xuất và không được xuấtĐóng gói ở cấp packagePhương thức getter và setterẨn thông tin trong GoÔn tập: hồ sơ học sinh10Generics (Go 1.18 trở lên)
Giới thiệu về GenericsTham số kiểuRàng buộc kiểuStruct tổng quátGiải pháp thay thế cho phương thức tổng quátÔn tập: tập hợp tổng quát13Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếMẫu SingletonMẫu FactoryMẫu Abstract FactoryMẫu ObserverMẫu Strategy2Tìm hiểu chuyên sâu về kiểu dữ liệu và struct
Kiểu cơ bản và kiểu tổng hợpĐịnh nghĩa kiểu dữ liệu tùy chỉnhThẻ structStruct ẩn danhStruct lồng nhauGiá trị zero và giá trị mặc địnhÔn tập: sổ liên lạc5Ưu tiên kết hợp hơn kế thừa
Vì sao Go không có kế thừaNhập môn nhúng structTự động nâng phương thứcNhúng nhiều structNhúng và kết tậpChe khuất phương thức được nhúngÔn tập: hệ phân cấp nhân viên8Xử lý lỗi và lập trình hướng đối tượng
Giao diện errorCác kiểu lỗi tùy chỉnhBọc lỗi với fmt.ErrorfLỗi sentinelerrors.Is() và errors.As()Panic, defer và recoverÔn tập: trình phân tích tệp3Con trỏ và bộ nhớ
Cơ bản về con trỏ trong GoCon trỏ đến structTruyền theo giá trị và tham chiếuHàm new()Thu gom rác trong GoÔn tập: xây dựng danh sách liên kết6Đa hình trong Go
Đa hình qua interfaceĐịnh kiểu vịt trong GoQuy tắc thỏa mãn interfaceCác tập hợp đa hìnhTiêm phụ thuộcÔn tập: bộ xử lý thanh toán9Lập trình đồng thời và lập trình hướng đối tượng
Cơ bản về goroutineChannel và giao tiếpChannel có bộ đệm và không có bộ đệmCâu lệnh selectsync.Mutex và sync.RWMutexsync.WaitGroupThiết kế struct an toàn luồngÔn tập: worker pool12Các khái niệm OOP nâng cao
Mẫu tùy chọn hàmMẫu Builder trong GoChuỗi phương thứcBí danh kiểu dữ liệu và định nghĩa kiểuCơ bản về reflectionTổng quan về tạo code15Dự án: Quản lý thư viện
Tổng quan và cấu trúc dự ánStruct về sách và người dùngTự luyện tập: Trình biên dịch Go online