[Bài 15] Sử dụng Page Factory trong POM

I. Sử dụng Page Factory

Xem hướng dẫn ở nhiều page, chắc các bạn cũng quen thuộc với Page Factory rồi, nay mình sẽ sử dụng nó để tối ưu code hiện tại. Page Factory là phần mở rộng của Page Object Model, nó giúp khởi tạo các đối tượng WebElement và giảm thiểu code dài dòng.

Login trước khi có sử dụng Page Factory:

public class LoginPage {
	public String user_login = "user_login";
	public String user_pass = "user_pass";
	public String submitBtn = "wp-submit";

	WebDriver driver;

	public LoginPage(WebDriver driver) {
		this.driver = driver;
	}

	public void login(String userName, String password) {
		driver.findElement(By.id(user_login)).sendKeys(userName);
		driver.findElement(By.id(user_pass)).sendKeys(password);
		driver.findElement(By.id(submitBtn)).click();
	}

}

Login Page sau khi có sử dụng Page Factory:

public class LoginPage {
	
	@FindBy (id = "user_login")
	WebElement user_login;
	
	@FindBy (id = "user_pass")
	WebElement user_pass;
	
	@FindBy (id = "wp-submit")
	WebElement submitBtn;
	

	WebDriver driver;

	public LoginPage(WebDriver driver) {
		this.driver = driver;
		PageFactory.initElements(driver, this);
	}

	public void login(String userName, String password) {
		user_login.sendKeys(userName);
		user_pass.sendKeys(password);
		submitBtn.click();
	}

}

Ta thấy cách khai báo một WebElement khá rõ ràng

@FindBy (id = "user_login")
WebElement user_login;

Nếu Element đó được xác định bằng name, css, xpath… thì bạn thay tương ứng vào chỗ “id” là được.

Hàm khởi tạo (constructor) sẽ thay đổi vì bây giờ sẽ sử dụng thêm PageFactory.

public LoginPage(WebDriver driver) {
	this.driver = driver;
	PageFactory.initElements(driver, this);
}

Tương tự, ta sẽ xử lý nốt cái page AddNewPostPage:

public class AddNewPostPage {

	public String URL_addNew = "http://localhost/wp/wp-admin/post-new.php";

	@FindBy(id = "content_ifr")
	WebElement iframe;

	@FindBy(id = "title")
	WebElement titleID;

	@FindBy(id = "tinymce")
	WebElement bodyID;

	@FindBy(id = "publish")
	WebElement publishBtn;

	@FindBy(css = "#message a")
	WebElement linkNewPost;

	@FindBy(css = "#edit-slug-box > strong")
	WebElement permalink;

	WebDriver driver;
	WebDriverWait wait;

	public AddNewPostPage(WebDriver driver) {
		this.driver = driver;
		wait = new WebDriverWait(driver, 20);
		PageFactory.initElements(driver, this);

	}

	public void addANewPost(String title, String body) {
		titleID.sendKeys(title);
		driver.switchTo().frame(iframe);
		bodyID.sendKeys(body);
		driver.switchTo().defaultContent();
		wait.until(ExpectedConditions.visibilityOf(permalink));
		publishBtn.click();
	}

	public void goToDetailPage() {
		linkNewPost.click();
	}

}

LƯU Ý: sau khi các bạn copy code của mình, sẽ bị báo lỗi rất nhiều do sử dụng các method của các package khác. Các bạn hãy sử dụng Ctrl+Shift+O để Eclipse tự động import thư viện cần thiết.

Bạn có thể dùng live template của Intellij để viết cho nhanh hơn.


II. Page Factory In-depth

Q: Hey man, vậy thì chính xác là Page Factory làm gì?

A: Sau khi khai báo WebElement và Locator, thì 2 cái này phải được liên kết với nhau. Có nghĩa là WebElement sẽ luôn luôn được tìm thấy bởi sử dụng Locator thông qua annotation FindBy. Và thực hiện công việc trên, ta cần khởi tạo Element thông qua constructor:

PageFactory.initElements(driver, this);

Q: Ơ, có nghĩa là các WebElement sẽ được tìm thấy ngay khi khởi tạo à?

A: Không. Khi khởi tạo, các WebElement sẽ chưa được tìm thấy. Khởi tạo chỉ để tạo ra LIÊN KẾT giữa WebElement và Locator. Khi nào WebElement đó được sử dụng thì chúng mới được tìm kiếm dựa trên các biến loại WebElement đã được khai báo ở trên.

Q: Ơ, Nếu WebElement đó được sử dụng nhiều lần thì nó tiếp tục tìm kiếm nhiều lần à?

A: Câu hỏi hay. Chính xác là như vậy, nó sẽ được tìm kiếm mỗi lần sử dụng. Tuy nhiên, có 1 cách để chỉ tìm 1 lần rồi sử dụng lại, đó là sử dụng annotation @CacheLookup. Ví dụ:

@FindBy (id = "user_login")
@CacheLookup
WebElement user_login;

Q: Một câu hỏi ngoài luồng: bao giờ thì series này kết thúc thế?

A: Mình chịu, biết đến đâu, viết đến đó. 😀

0 0 votes
Article Rating
Subscribe
Notify of
guest
9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Thùy Linh
Thùy Linh
3 years ago

Anh cho em hỏi tại sao mình khởi tạo WebDriver driver; rồi. Nhưng vẫn phải thêm this.driver = driver nữa ạ? Mục đích của phần this.driver = driver này để làm gì ạ? Vì toàn bộ những lệnh bên dưới mình đều dùng driver chứ không phải this.driver.
Em cảm ơn anh!

Thùy Linh
Thùy Linh
3 years ago
Reply to  Giang Nguyen

Oh, do em chưa hiểu rõ ạ
Em cảm ơn a đã giải thích :))

HoangNguyen
HoangNguyen
10 months ago

Anh Giang cho em hỏi chút là với mấy dynamic element thì bình thường e dùng xpath và [contains()], [starts-with()] để tìm.
Vậy với @FindBy mình có thể dùng contains, starts-with để find dynamic element ko a?
Thanks a

HoangNguyen
HoangNguyen
10 months ago
Reply to  Giang Nguyen

em hỏi thêm 1 chút là ngoài giảm code dài dòng, nó còn có thêm benefit nào lớn nữa ko anh?
framework em đang làm ko dùng page factory nên code hơi dài, em tính đề xuất dùng page factory để refactor lại nhưng ko biết còn benefit nào lớn ko? để thuyết phục PO về priority.
Thanks anh

quan khung
quan khung
3 months ago
Reply to  HoangNguyen

Cu de im vay chu refactor lam gi. Project moi thi duoc