NỘI DUNG BÀI HỌC
✅ Triển khai liên kết trang (Page Navigation)
🔆 Khi nào không cần liên kết trang?
✅ Tại sao nên liên kết trang trong Page Object Model
Chúng ta xét đoạn code MenuTest hôm trước:
package com.anhtester.Bai17_PageObjectModel.testcases;
import com.anhtester.Bai17_PageObjectModel.pages.LoginPage;
import com.anhtester.Bai17_PageObjectModel.pages.MenuPage;
import com.anhtester.common.BaseTestTaurusApp;
import org.testng.annotations.Test;
public class MenuTest extends BaseTestTaurusApp {
LoginPage loginPage;
MenuPage menuPage;
@Test
public void testSearchTable() {
loginPage = new LoginPage();
loginPage.login("admin", "admin");
loginPage.verifyLoginSuccess();
downloadDataFromServer(2);
menuPage = new MenuPage();
menuPage.searchTable("Table 1");
menuPage.checkTableResultTotal(1);
}
}
❌ Ở đoạn code tại MenuTest có vấn đề như sau:
- Sau khi kiểm tra đăng nhập thành công loginPage.verifyLoginSuccess(), bạn tạo một instance mới của MenuPage bằng new MenuPage(). Điều này không đảm bảo rằng MenuPage được liên kết chính xác với trạng thái hiện tại của ứng dụng (tức là giao diện đã chuyển sang màn hình menu).
- Nếu không có cơ chế liên kết rõ ràng, bạn có thể gặp lỗi khi MenuPage cố gắng thao tác trên giao diện chưa sẵn sàng. (nghĩa là có thể login chưa thành công mà đã thao tác tiếp đến trang Menu)
🔆 Lý do nên liên kết trang
- Phản ánh luồng thực tế của ứng dụng:
- Trong một ứng dụng (web hoặc mobile), các trang thường được liên kết theo một luồng điều hướng cụ thể. Ví dụ: từ trang đăng nhập (LoginPage) sang trang menu (MenuPage) sau khi đăng nhập thành công. Việc liên kết trang trong code giúp mô phỏng chính xác hành vi này, làm cho test script giống với cách người dùng thực sự sử dụng ứng dụng.
- Trong một ứng dụng (web hoặc mobile), các trang thường được liên kết theo một luồng điều hướng cụ thể. Ví dụ: từ trang đăng nhập (LoginPage) sang trang menu (MenuPage) sau khi đăng nhập thành công. Việc liên kết trang trong code giúp mô phỏng chính xác hành vi này, làm cho test script giống với cách người dùng thực sự sử dụng ứng dụng.
- Tăng tính mạch lạc và dễ đọc:
- Khi bạn liên kết trang (ví dụ: MenuPage menuPage = loginPage.login(...)), code thể hiện rõ ràng mối quan hệ giữa các hành động và kết quả. Người đọc (bao gồm cả bạn hoặc đồng nghiệp) có thể dễ dàng hiểu rằng hành động đăng nhập dẫn đến trang menu mà không cần đoán mò.
- Nếu không liên kết, bạn phải tạo thủ công các instance mới (như new MenuPage()) mà không có sự kết nối rõ ràng với hành động trước đó, làm giảm tính trực quan.
- Giảm thiểu lỗi do trạng thái không đồng bộ:
- Nếu bạn không liên kết trang mà chỉ tạo instance mới (ví dụ: menuPage = new MenuPage() sau loginPage.login()), có nguy cơ MenuPage được khởi tạo trước khi giao diện thực sự chuyển sang màn hình menu. Liên kết trang trong phương thức (như login hoặc verifyLoginSuccess) cho phép bạn kiểm soát thời điểm trả về trang tiếp theo, đảm bảo giao diện đã sẵn sàng.
- Hỗ trợ kiểm tra điều hướng (navigation testing):
- Liên kết trang cho phép bạn kiểm tra xem điều hướng có hoạt động đúng hay không. Ví dụ: Nếu login trả về MenuPage nhưng giao diện thực tế vẫn ở trang đăng nhập, bạn có thể phát hiện lỗi điều hướng ngay lập tức thông qua assertion trong MenuPage.
- Liên kết trang cho phép bạn kiểm tra xem điều hướng có hoạt động đúng hay không. Ví dụ: Nếu login trả về MenuPage nhưng giao diện thực tế vẫn ở trang đăng nhập, bạn có thể phát hiện lỗi điều hướng ngay lập tức thông qua assertion trong MenuPage.
- Tuân theo nguyên tắc POM:
- POM khuyến khích mỗi page object đại diện cho một màn hình hoặc trạng thái cụ thể của ứng dụng, và các phương thức trong page object nên phản ánh các hành động người dùng thực hiện. Liên kết trang là cách tự nhiên để thể hiện sự chuyển đổi giữa các trạng thái này.
✅ Triển khai liên kết trang (Page Navigation)
Tại class LoginPage thay vì trả về void
thì chúng ta trả về trang cần liên kết đến sau khi login thành công, là trang MenuPage.
public MenuPage login(String username, String password) {
usernameField.click();
usernameField.sendKeys(username);
passwordField.click();
passwordField.sendKeys(password);
loginButton.click();
return new MenuPage();
}
Sau đó ở cuối hàm thì return new MenuPage() để khởi tạo trang cần liên kết.
Sang class MenuTest chỉnh lại phần khởi tạo đối tượng trang menu:
package com.anhtester.Bai18_PageNavigation.testcases;
import com.anhtester.Bai18_PageNavigation.pages.LoginPage;
import com.anhtester.Bai18_PageNavigation.pages.MenuPage;
import com.anhtester.common.BaseTestTaurusApp;
import org.testng.annotations.Test;
public class MenuTest extends BaseTestTaurusApp {
LoginPage loginPage;
MenuPage menuPage;
@Test
public void testSearchTable() {
loginPage = new LoginPage();
//Khởi tạo trang Menu thông qua việc Login nếu thành công
menuPage = loginPage.login("admin", "admin");
loginPage.verifyLoginSuccess();
downloadDataFromServer(2);
//menuPage = new MenuPage(); //không cần khởi tạo trang Menu riêng
menuPage.searchTable("Table 1");
menuPage.checkTableResultTotal(1);
}
}
Khi đó chúng ta lấy đối tượng menuPage = loginPage.login() luôn để khi login thành công thì trả về khởi tạo trang MenuPage, khi đó đối tượng trang menuPage đã mang giá trị khởi tạo class thành công. Mà không cần khởi tạo riêng lẻ.
Việc liên kết trang giúp:
- Phản ánh đúng luồng ứng dụng.
- Tăng tính rõ ràng, an toàn, và khả năng bảo trì của code.
- Giảm thiểu lỗi do trạng thái không đồng bộ.
Đó là lý do tại sao trong POM, liên kết trang được khuyến khích. Trong trường hợp của bạn (từ LoginPage sang MenuPage), liên kết trong login là cách tự nhiên nhất để thể hiện rằng đăng nhập thành công dẫn đến menu.
🔆 Khi nào không cần liên kết trang?
- Ứng dụng đơn giản: Nếu ứng dụng chỉ có một màn hình hoặc không có điều hướng rõ ràng (ví dụ: một form tĩnh), bạn có thể không cần liên kết.
- Test không phụ thuộc vào luồng: Nếu bạn chỉ kiểm tra một trang cụ thể mà không quan tâm đến cách đến đó, việc tạo instance độc lập có thể đủ.
Tuy nhiên, trong hầu hết các ứng dụng thực tế (như ứng dụng có đăng nhập, menu, cài đặt, v.v.), liên kết trang là cách tiếp cận tiêu chuẩn.