Bài này mình sẽ nói về cách sử dụng Page Object sao cho tốt nhất, tránh phải những sai lầm khi mới học về Page Object.
Nội dung bài viết
I. Page Object không có nghĩa là mỗi Page HTML là 1 class
Page Object là thuật ngữ dùng chung, miêu tả cách model 1 page HTML thành object trong lập trình.
Page ở đây phải hiểu là page hoặc 1 thành phần của page
Điều này sẽ làm cho các class của bạn sẽ được chẻ nhỏ ra, tránh trường hợp page phức tạp, kéo dài cả mấy trăm dòng.
Các thành phần của page có thể được model như sau:

II. Không nên sử dụng Selenium code ở phần Test.
- Khi mô hình hóa thành Page Object thì có nghĩa là bạn đã tạo ra 1 layer bên trên tầng tương tác với browser. Các layer cần tương tác với thằng kế tiếp nó, không nên tương tác nhảy cóc.

Ví dụ:
@Test public void searchPage(){ ... page.searchFor("funny cats"); System.out.println(driver.getCurrentUrl()); (1) ... }
Như trên ví dụ này, mình đang sử dụng page
mà chỗ (1) mình lại dùng driver
của Selenium, như vậy là mình đang tương tác nhảy cóc.
III. Khi đặt tên public method phải đặt theo business của application
Không nên sử dụng các thuật ngữ riêng của web, hãy sử dụng các từ ngữ của business.
E.g: Thay thế setQuery() + submit() bằng searchFor()
@Test void name() { SearchForm searchPage = new SearchForm(driver); searchPage.setQuery("funny cats"); searchPage.submit(); }
Nên đặt tên method như sau:
@Test void name() { SearchForm searchPage = new SearchForm(driver); searchPage.searchFor("funny cats"); }
IV. Nên sử dụng kỹ thuật Lazy Loading
Nếu bạn đã làm java được 1 thời gian thì chắc sẽ hiểu và hay sử dụng immutable class, nhưng áp dụng vào page object sẽ không work. Vì immutable class có nghĩa là bạn phải khởi tạo object với trạng thái cố định. Nhưng web page là 1 loại object luôn thay đổi trạng thái (mutable) chứ không phải immutable.
Ví dụ: 1 WebElement có thể ẩn hiện trong khi mình sử dụng trang web, chứ ban đầu nó không xuất hiện. Nếu mình findElemenet đó ngay thời điểm đầu tiên khi khởi tạo page –> NoSuchElementException. Hoặc lúc trước đã tìm kiếm được, lúc sau Element bị thay đổi –> StaleElementReferenceException.
Do đó, ta cần phải tìm kiếm WebElement trước mỗi lần mà ta định tương tác với WebElement đó.
Lazy Loading có nghĩa là đợi đến khi nào tương tác thì mới khởi tạo.
Có nhiều cách để Lazy Loading, cách dễ nhất là sử dụng PageFactory của selenium.
V. Throw exception khi khởi tạo sai page
Bạn có thể gặp trường hợp sau đây:
- Login
- Vào homepage, bấm vào link đến page A
Lỗi NoSuchElementException xuất hiện ở step 2, bạn nghĩ là bạn đã lấy sai locator của đường link. Bạn check lại WebElement và thấy là bạn lấy đúng locator. Bạn run lại test failed và phát hiện ra là login không thành công, nó vẫn ở page Login. 😐
Bạn nên có cơ chế throw exception khi mà khởi tạo sai page, mình mới nghĩ ra 3 cách sau:
- sử dụng Loadable component
- sử dụng custom PageFactory
- 1 vài dòng code check trên constructor của page mình muốn khởi tạo
public SearchPage(WebDriver driver) { String pageTitle = driver.getTitle(); if (!pageTitle.equals("Search")) { throw new IllegalArgumentException( String.format("page is not search page, it has un-expected title %s", pageTitle)); } // ... }
VI. Không nên có method Assert ở trong Page Object
Ví dụ
public void assertPageTitleIs(String expectedTitle) { assertEquals(expectedTitle, driver.getTitle()); }
Lý do là:
- Làm cho Page của bạn và Assertion Framework bị gắn chặt vào nhau, sau này bạn muốn đổi sang Assertion library khác là rất khó
- Page Object chỉ nên trả lại trạng thái của page, việc assert là việc của phần test.