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 Java của Coddy. Bài học 83 trên 87.
Thử thách
DễChúc mừng bạn đã xây dựng Hệ thống quản lý thư viện! Đã đến lúc kết hợp mọi thứ và xác minh rằng tất cả thành phần đều hoạt động chính xác như một hệ thống thống nhất. Bạn sẽ tạo một kịch bản kiểm thử toàn diện để kiểm tra tất cả tính năng đã xây dựng trong dự án này.
Bạn sẽ làm việc với cả bảy tệp trong hệ thống hoàn chỉnh của mình:
Book.java: Lớp Book có các thuộc tính isbn, title, author, isAvailable, borrowedBy và tất cả phương thức liên quan, bao gồmgetDetails().User.java: Lớp User có các thuộc tính id, name, danh sách borrowedBooks và các phương thức mượn, trả sách.LibraryException.java: Lớp ngoại lệ tùy chỉnh cơ sở.BookNotAvailableException.java: Ngoại lệ dành cho sách không có sẵn.LibraryAdmin.java: Giao diện quản trị và phần triển khai AdminService.Library.java: Lớp Library hoàn chỉnh với tất cả phương thức: thêm, xóa sách, đăng ký người dùng, mượn, trả sách, tìm kiếm và xử lý ngoại lệ.Main.java: Bài kiểm thử tích hợp minh họa cách toàn bộ hệ thống hoạt động cùng nhau.
Trong lớp Main, bạn sẽ xử lý một loạt lệnh để kiểm thử mọi tính năng chính của hệ thống thư viện. Các lệnh được nhập dưới dạng một chuỗi duy nhất, phân tách bằng dấu phẩy, theo các định dạng sau:
ADD_BOOK:isbn:title:author, Thêm sách thông qua AdminServiceREGISTER_USER:id:name, Đăng ký người dùng thông qua AdminServiceBORROW:userId:isbn, Mượn sách (có xử lý ngoại lệ)RETURN:userId:isbn, Trả sáchSEARCH_TITLE:keyword, Tìm sách theo tiêu đềSEARCH_AUTHOR:keyword, Tìm sách theo tác giảREMOVE_BOOK:isbn, Xóa sách thông qua AdminService
Xử lý từng lệnh và in ra kết quả phù hợp:
- ADD_BOOK:
Added: [title] - REGISTER_USER:
Registered: [name] - BORROW: In thông báo thành công hoặc
Error: [exception message] - RETURN:
[userName] returned [bookTitle] - SEARCH_TITLE: In
Search '[keyword]':, theo sau là thông tin chi tiết của từng sách phù hợp, hoặcNo results - SEARCH_AUTHOR: Theo cùng định dạng với tìm kiếm theo tiêu đề
- REMOVE_BOOK:
Removed: [isbn]hoặcCannot remove: [isbn]
Sau khi xử lý tất cả lệnh, in bản tóm tắt cuối cùng:
--- Final Status ---Books: [count]Users: [count]- Với từng người dùng, in
[name]: [borrowedCount] book(s)
Bạn sẽ nhận một đầu vào: chuỗi lệnh được phân tách bằng dấu phẩy.
Ví dụ, với đầu vào ADD_BOOK:ISBN-001:Clean Code:Robert Martin,ADD_BOOK:ISBN-002:Effective Java:Joshua Bloch,REGISTER_USER:U001:Alice,REGISTER_USER:U002:Bob,BORROW:U001:ISBN-001,BORROW:U002:ISBN-001,SEARCH_TITLE:java,RETURN:U001:ISBN-001,REMOVE_BOOK:ISBN-001, đầu ra sẽ là:
Added: Clean Code
Added: Effective Java
Registered: Alice
Registered: Bob
Alice borrowed Clean Code
Error: Book not available: ISBN-001
Search 'java':
[ISBN-002] Effective Java by Joshua Bloch
Alice returned Clean Code
Removed: ISBN-001
--- Final Status ---
Books: 1
Users: 2
Alice: 0 book(s)
Bob: 0 book(s)Thử thách cuối cùng này xác minh rằng tất cả thành phần, lớp, giao diện, ngoại lệ và logic thư viện hoạt động liền mạch cùng nhau. Bạn đã xây dựng một Hệ thống quản lý thư viện hoàn chỉnh và vững chắc!
Tự làm thử
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Đọc các lệnh được phân tách bằng dấu phẩy
String input = scanner.nextLine();
String[] commands = input.split(",");
// Tạo Library và AdminService
Library library = new Library();
AdminService adminService = new AdminService(library);
// Xử lý từng lệnh
for (String command : commands) {
String[] parts = command.split(":");
String operation = parts[0];
if (operation.equals("ADD_BOOK")) {
String isbn = parts[1];
String title = parts[2];
String author = parts[3];
if (adminService.addBook(isbn, title, author)) {
System.out.println("Added: " + title);
}
} else if (operation.equals("REMOVE_BOOK")) {
String isbn = parts[1];
if (adminService.removeBook(isbn)) {
System.out.println("Removed: " + isbn);
} else {
System.out.println("Cannot remove: " + isbn);
}
} else if (operation.equals("REGISTER_USER")) {
String id = parts[1];
String name = parts[2];
if (adminService.registerUser(id, name)) {
System.out.println("Registered: " + name);
}
} else if (operation.equals("BORROW")) {
String userId = parts[1];
String isbn = parts[2];
try {
String result = library.borrowBook(userId, isbn);
System.out.println(result);
} catch (LibraryException e) {
System.out.println("Error: " + e.getMessage());
}
}
// TODO: Thêm xử lý lệnh RETURN
// TODO: Thêm xử lý lệnh SEARCH_TITLE
// TODO: Thêm xử lý lệnh SEARCH_AUTHOR
}
// TODO: In ra trạng thái cuối cùng
// --- Final Status ---
// Sách: [count]
// Người dùng: [count]
// Với mỗi người dùng: [name]: [borrowedCount] cuốn sách
System.out.println("Operations completed");
}
}
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcTrường (thuộc tính)Phương thức khởi tạoNạp chồng phương thức khởi tạoÔn tập: Máy tính đơn giản4Kế thừa
Kế thừa cơ bản (extends)Từ khóa superGhi đè phương thức (@Override)Chuỗi gọi hàm khởi tạoLớp ObjectKế thừa đơn và đa cấpVì sao không hỗ trợ kế thừa nhiều lớpÔn tập: Phân cấp lớp Employee7Phương thức đặc biệt và lớp Object
Phương thức toString()equals() và hashCode()Phương thức clone()compareTo() và ComparableGiao diện ComparatorÔn tập: sắp xếp tùy chỉnh10Xử lý ngoại lệ trong OOP
Phân cấp lớp ngoại lệNgoại lệ tùy chỉnhLỗi có kiểm tra và không kiểm traMẫu try-with-resourcesÔn tập: người dùng đã xác thực13Dự án: Quản lý thư viện
Tổng quan dự án và thiết kế UMLLớp sách và người dùngHệ thống mượn sáchChức năng tìm kiếmGiao diện quản trịTích hợp xử lý ngoại lệKiểm thử và tích hợp2Bộ điều chỉnh quyền truy cập và đóng gói
Tổng quan về các mức truy cậpPhương thức getter và setterẨn thông tinTừ khóa finalÔn tập: Trình quản lý tài khoản ngân hàng5Tính đa hình
Kiến thức cơ bản về nạp chồng phương thứcGhi đè phương thức (thời gian chạy)Chuyển kiểu lên và chuyển kiểu xuốngToán tử instanceofLớp và phương thức trừu tượngÔn tập: máy tính hình học8Khái niệm OOP nâng cao
Kết hợp và kế thừaKết tập và hợp thànhLớp bên trong, lớp lồng nhau và lớp ẩn danhKiểu enum và phương thức enumBản ghi (Java 16+)Lớp sealed (Java 17+)3Thuộc tính lớp và thành viên tĩnh
Biến của instance và biến tĩnhPhương thức tĩnhKhối tĩnhHằng số (static final)Ôn tập: bộ đếm và tiện ích6Giao diện và lớp trừu tượng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnPhương thức mặc định và tĩnh trong giao diệnLớp trừu tượng và giao diệnGiao diện hàmÔn tập: hệ thống thanh toán9Kiểu tổng quát
Giới thiệu về kiểu tổng quátLớp tổng quátPhương thức tổng quátTham số kiểu có giới hạnKý tự đại diện (?, extends, super)Ôn tập: vùng chứa tổng quát12Mẫu thiết kế, phần 2
Mẫu CommandMẫu AdapterMẫu DecoratorMẫu Template MethodMẫu StateMẫu CompositeMẫu IteratorTự luyện tập: Trình biên dịch Java online