Nội dung bài học

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 tối ưu hơn và giảm thiểu code ngắn gọn hơn.

Giới thiệu Page Factory

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 tối ưu hơn và giảm thiểu code ngắn gọn hơn.

Nó được sử dụng để khởi tạo các đối tượng Trang hoặc để khởi tạo chính đối tượng Trang. Nó cũng được sử dụng để khởi tạo các hành động xử lý mà không cần sử dụng cú pháp driver.findElement / driver.findElements.

Có hai bước đơn giản để sử dụng Page Factory trong các dự án Selenium:

1. Sử dụng chú thích @FindBy - Không giống như cách tiếp cận thông thường để khởi tạo các phần tử trang web bằng FindElement hoặc FindElements , Page Factory sử dụng chú thích @FindByCác chú thích này được sử dụng trong Page Factory mang tính mô tả. Hơn nữa, chúng giúp cải thiện khả năng đọc mã mà chúng ta sẽ thảo luận trong phần tiếp theo. Nó cung cấp cú pháp sau để xác định vị trí các phần tử web:


2 . Khởi tạo các phần tử bằng initElements ()
- Đây là một phương thức tĩnh được sử dụng để khởi tạo các phần tử web mà chúng định vị bằng cách sử dụng @FindBy trên hoặc (các) chú thích khác, đặt nó vào chổ hàm xây dựng khởi tạo lớp trang.

PageFactory.initElements(WebDriver driver, java.lang.Class.pageObjectClass);


Sử dụng Page Factory trong POM


Chúng ta thấy class SignInPage bài trước khi chưa dùng Page Factory:

public class SignInPage {

	private WebDriver driver;

	private By headerPageText = By.xpath("//a[normalize-space()='Forgot Username/Password?']");
	private By emailInput = By.id("EmailInputEmail");
	private By passwordInput = By.id("PasswordInputPassword");
	private By signinBtn = By.id("SignInButton");
	private By errorMsgText = By.id("signInError");

	private By pinInput = By.id("Pin");
	private By submitBtn = By.id("RequestPinForm_SubmitButton");
	private By backBtn = By.id("RequestPinForm_Back");
	private By resetPintBtn = By.id("RequestPinForm_ResetPin");

	// Khởi tạo class khi được gọi và truyền driver vào để các thành phần trong
	public SignInPage(WebDriver driver) {
		this.driver = driver;
	}

	// Sau khi thực hiện click Submit thì khởi tạo trang DashboardPage
	public void signin(String username, String password, String Pin) throws Exception {
		enterEmail(username);
		enterPassword(password);
		clickSignIn();
		Thread.sleep(1000);
		enterPin(Pin);
		clickSubmit();
	}

     public void enterEmail(String email) {
		WebElement emailTxtBox = driver.findElement(emailInput);
		if (emailTxtBox.isDisplayed())
			emailTxtBox.sendKeys(email);
	}

	public void enterPassword(String password) {
		WebElement passwordTxtBox = driver.findElement(passwordInput);
		if (passwordTxtBox.isDisplayed())
			passwordTxtBox.sendKeys(password);
	}

	public void clickSignIn() {
		WebElement signin = driver.findElement(signinBtn);
		if (signin.isDisplayed()) {
			signin.click();
		}
	}

	public void clickSubmit() {
		WebElement submit = driver.findElement(submitBtn);
		if (submit.isDisplayed()) {
			submit.click();
		}
	}

	public void enterPin(String PIN) {
		driver.findElement(pinInput).sendKeys(PIN);
	}

	public void clickBack() {
		driver.findElement(backBtn).click();
	}

	public void clickResetPin() {
		driver.findElement(resetPintBtn).click();
	}

}


Khi chúng ta áp dụng dùng Page Factory thì nó sẽ như này:

public class SignInPageFactory {

	private WebDriver driver;

	@FindBy(xpath = "//a[normalize-space()='Forgot Username/Password?']")
	private WebElement headerPageText;

	@FindBy(id = "EmailInputEmail")
	private WebElement emailInput;

	@FindBy(id = "PasswordInputPassword")
	private WebElement passwordInput;

	@FindBy(id = "SignInButton")
	private WebElement signinBtn;

	@FindBy(id = "signInError")
	private WebElement errorMsgText;

	@FindBy(id = "Pin")
	private WebElement pinInput;
	@FindBy(id = "RequestPinForm_SubmitButton")
	private WebElement submitBtn;
	@FindBy(id = "RequestPinForm_Back")
	private WebElement backBtn;
	@FindBy(id = "RequestPinForm_ResetPin")
	private WebElement resetPintBtn;

	// Khởi tạo class khi được gọi và truyền driver vào để các thành phần trong
	// Và khởi tạo initElements
	public SignInPageFactory(WebDriver driver) {
		this.driver = driver;
		PageFactory.initElements(driver, this);
	}

	// Chúng ta viết hàm signin không cần dùng các hàm bổ trợ enter hay click nữa
	public void signin(String username, String password, String Pin) throws Exception {
		emailInput.sendKeys(username);
		passwordInput.sendKeys(password);
		signinBtn.click();
		Thread.sleep(1000);
		pinInput.sendKeys(Pin);
		submitBtn.click();
	}
}

 

Vậy là xong. Gọn ràng hơn chứ hả.

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

@FindBy(id = "EmailInputEmail")
private WebElement emailInput;

Nếu dùng xpath hay name hay classname thì chứ thay vào chổ "id" là xong.

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

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


Diễn giải thêm chổ Page Factory:


Vậy thì chính xác là Page Factory làm gì?

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 sử dụng bởi 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);

 

- Các WebElement sẽ KHÔNG được tìm thấy ngay khi khởi tạo. 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.


-
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 hay sao đây??

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 = "EmailInputEmail")
@CacheLookup
private WebElement emailInput;

Ngoài ra, bạn có thể sử dụng @FindAll với nhiều chú thích @FindBy để tìm kiếm các phần tử khớp với bất kỳ bộ định vị nào đã cho:

@FindAll({@FindBy(how=How.ID, using="username"),
	@FindBy(className="username-field")})
private WebElement user_name;


Hoặc khi cần tìm danh sách các phần tử trên một trang (findElements) thì chúng ta dùng @FindBys như sau:

@FindBys(@FindBy(css="div[class='yt-lockup-tile yt-lockup-video']")))
private List<WebElement> videoElements;

Và cách khác để viết đơn giản hơn nữa là:

@FindBy(how=How.CSS,using="div[class='yt-lockup-tile yt-lockup-video']")
private List<WebElement> videoElements;


==> Vậy là xong rồi.

Phần DashboardPage viết tương tự thôi nào =))


Cộng đồng Automation Testing Việt Nam

🌱 Facebook Fanpage: Anh Tester
🌱 Telegram
Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

  • Anh Tester

    Đường dẫu khó chân vẫn cần bước đi
    Đời dẫu khổ tâm vẫn cần nghĩ thấu


Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ kiến thức lên trang

Bạn có thể đăng bài để chia sẻ kiến thức, bài viết của chính bạn lên trang Anh Tester Blog

Danh sách bài học