Mô hình đối tượng trang & Nhà máy trong Selenium
Mô hình đối tượng trang là gì?
Mô hình đối tượng trang (POM) là một mẫu thiết kế, được sử dụng phổ biến trong tự động hóa thử nghiệm nhằm tạo Kho lưu trữ đối tượng cho các thành phần giao diện người dùng web. Ưu điểm của mô hình là giảm sự trùng lặp mã và cải thiện việc bảo trì thử nghiệm.
Theo mô hình này, đối với mỗi trang web trong ứng dụng, cần có một Lớp trang tương ứng. Lớp Trang này sẽ xác định các WebElements của trang web đó và cũng chứa các phương thức Trang thực hiện các thao tác trên các WebElements đó. Tên của các phương thức này phải được đặt theo nhiệm vụ mà chúng đang thực hiện, tức là nếu trình tải đang đợi cổng thanh toán xuất hiện, thì tên phương thức POM có thể là waitForPaymentScreenDisplay().
Tại sao mô hình đối tượng trang?
Bắt đầu Tự động hóa giao diện người dùng trong Selenium WebDriver KHÔNG phải là một nhiệm vụ khó khăn. Bạn chỉ cần tìm các phần tử, thực hiện các thao tác trên đó.
Hãy xem xét tập lệnh đơn giản này để đăng nhập vào một trang web
Như bạn có thể quan sát, tất cả những gì chúng ta đang làm là tìm các phần tử và điền giá trị cho các phần tử đó.
Đây là một kịch bản nhỏ. Bảo trì tập lệnh có vẻ dễ dàng. Nhưng theo thời gian, bộ thử nghiệm sẽ phát triển. Khi bạn thêm ngày càng nhiều dòng vào mã của mình, mọi thứ trở nên khó khăn hơn.
Vấn đề chính với việc bảo trì tập lệnh là nếu 10 tập lệnh khác nhau đang sử dụng cùng một thành phần trang, thì với bất kỳ thay đổi nào trong thành phần đó, bạn cần phải thay đổi tất cả 10 tập lệnh. Việc này tốn thời gian và dễ xảy ra lỗi.
Cách tiếp cận tốt hơn để bảo trì tập lệnh là tạo một tệp lớp riêng biệt để tìm các phần tử web, điền hoặc xác minh chúng. Lớp này có thể được sử dụng lại trong tất cả các tập lệnh sử dụng phần tử đó. Trong tương lai, nếu có thay đổi trong thành phần web, chúng ta cần thực hiện thay đổi chỉ trong 1 tệp lớp chứ không phải 10 tập lệnh khác nhau.
Cách tiếp cận này được gọi là Mô hình đối tượng trang trong Selenium. Nó giúp làm cho mã dễ đọc hơn, dễ bảo trì hơn và có thể tái sử dụng hơn.
Ưu điểm của POM
- Mẫu thiết kế đối tượng trang cho biết các hoạt động và luồng trong giao diện người dùng phải được tách biệt khỏi quá trình xác minh. Khái niệm này làm cho mã của chúng tôi sạch hơn và dễ hiểu hơn.
- Lợi ích thứ hai là kho đối tượng độc lập với các trường hợp thử nghiệm, vì vậy chúng ta có thể sử dụng cùng một kho đối tượng cho các mục đích khác nhau bằng các công cụ khác nhau. Ví dụ: chúng ta có thể tích hợp Mô hình đối tượng trang trong Selenium với TestNG/JUnit cho chức năng Kiểm tra và đồng thời với JBehave/Cucumber cho việc kiểm tra chấp nhận.
- Mã trở nên ít hơn và được tối ưu hóa nhờ các phương thức trang có thể sử dụng lại trong các lớp POM.
- Các phương thức có tên thực tế hơn, có thể dễ dàng ánh xạ với thao tác xảy ra trong giao diện người dùng. tức là nếu sau khi nhấp vào nút, chúng tôi đến trang chủ, tên phương thức sẽ giống như 'gotoHomePage()'.
Triển khai POM như thế nào?
POM đơn giản:
Đó là cấu trúc cơ bản của khung mô hình đối tượng Trang nơi tất cả các Thành phần Web của AUT và phương thức hoạt động trên các Thành phần Web này được duy trì bên trong một tệp lớp. Nhiệm vụ như xác minh phải tách biệt như một phần của Phương thức kiểm tra.
Hoàn thành ví dụ
Trường hợp thử nghiệm: Đi tới Trang demo Guru99.
Bước 1) Truy cập Trang demo Guru99
Bước 2) Tại trang chủ có dòng chữ kiểm tra “Guru99 Bank”
Bước 3) Đăng nhập vào ứng dụng
Bước 4) Xác minh rằng Trang chủ có chứa văn bản là “Id Manger: demo”
Đây là chúng tôi đang xử lý 2 trang
- Đăng nhập Trang
- Trang chủ (hiển thị khi bạn đăng nhập)
Theo đó chúng ta tạo 2 POM trong Selenium các lớp học
Trang đăng nhập Guru99 POM
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99Login { WebDriver driver; By user99GuruName = By.name("uid"); By password99Guru = By.name("password"); By titleText =By.className("barone"); By login = By.name("btnLogin"); public Guru99Login(WebDriver driver){ this.driver = driver; } //Set user name in textbox public void setUserName(String strUserName){ driver.findElement(user99GuruName).sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ driver.findElement(password99Guru).sendKeys(strPassword); } //Click on login button public void clickLogin(){ driver.findElement(login).click(); } //Get the title of Login Page public String getLoginTitle(){ return driver.findElement(titleText).getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Trang chủ Guru99 POM trong Selenium
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99HomePage { WebDriver driver; By homePageUserName = By.xpath("//table//tr[@class='heading3']"); public Guru99HomePage(WebDriver driver){ this.driver = driver; } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return driver.findElement(homePageUserName).getText(); } }
Guru99 POM đơn giản trong Selenium Kiểm tra trường hợp
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99HomePage; import pages.Guru99Login; public class Test99GuruLogin { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } /** * This test case will login in http://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); }
Page Factory là gì Selenium?
Nhà máy trang ở Selenium là một khái niệm khung Mô hình Đối tượng Trang có sẵn dành cho Selenium WebDriver nhưng nó rất tối ưu. 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 phần tử của lớp Trang mà không cần sử dụng “FindElement/s”.
Ở đây cũng vậy, chúng tôi tuân theo khái niệm tách biệt Kho lưu trữ đối tượng trang và Phương thức kiểm tra. Ngoài ra, với sự trợ giúp của lớp PageFactory trong Selenium, chúng tôi sử dụng chú thích @FindBy để tìm WebElement. Chúng tôi sử dụng phương thức initElements để khởi tạo các thành phần web
@FindBy có thể chấp nhận tagName, một phầnLinkText, tên, linkText, id, css, className, xpath dưới dạng các thuộc tính.
Hãy xem ví dụ tương tự như trên bằng cách sử dụng Page Factory
Trang đăng nhập Guru99 với Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99Login { /** * All WebElements are identified by @FindBy annotation */ WebDriver driver; @FindBy(name="uid") WebElement user99GuruName; @FindBy(name="password") WebElement password99Guru; @FindBy(className="barone") WebElement titleText; @FindBy(name="btnLogin") WebElement login; public Guru99Login(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Set user name in textbox public void setUserName(String strUserName){ user99GuruName.sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ password99Guru.sendKeys(strPassword); } //Click on login button public void clickLogin(){ login.click(); } //Get the title of Login Page public String getLoginTitle(){ return titleText.getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Trang chủ Guru99 với Trang Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99HomePage { WebDriver driver; @FindBy(xpath="//table//tr[@class='heading3']") WebElement homePageUserName; public Guru99HomePage(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return homePageUserName.getText(); } }
Guru99 TestCase với khái niệm Page Factory
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import PageFactory.Guru99HomePage; import PageFactory.Guru99Login; public class Test99GuruLoginWithPageFactory { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://demo.guru99.com/V4/"); } /** * This test go to http://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); } }
Cấu trúc dự án hoàn chỉnh sẽ giống như sơ đồ:
AjaxElementLocatorNhà máy
AjaxElementLocatorNhà máy là một khái niệm tải từng phần của PageFactory trong Selenium. Nó chỉ được sử dụng để tìm các phần tử web khi các phần tử đó được sử dụng trong bất kỳ thao tác nào. Nó chỉ định thời gian chờ cho WebElements cho lớp trang đối tượng. Một trong những ưu điểm chính của việc sử dụng mẫu PageFactory trong Selenium là Lớp AjaxElementLocatorFactory.
Ở đây, khi một thao tác được thực hiện trên một phần tử, việc chờ khả năng hiển thị của nó chỉ bắt đầu từ thời điểm đó. Nếu phần tử không được tìm thấy trong khoảng thời gian nhất định, Trường hợp thử nghiệm việc thực thi sẽ đưa ra ngoại lệ 'NoSuchElementException'.
Tổng kết
- Mô hình đối tượng trang trong Selenium WebDriver là một mẫu thiết kế Kho lưu trữ đối tượng.
- Selenium mô hình đối tượng trang tạo mã thử nghiệm của chúng tôi có thể duy trì và tái sử dụng.
- Page Factory là một cách tối ưu hóa để tạo kho lưu trữ đối tượng trong khái niệm khung Mô hình đối tượng trang.
- AjaxElementLocatorFactory là một khái niệm tải từng phần trong Page Factory - mẫu thiết kế đối tượng trang để chỉ xác định WebElements khi chúng được sử dụng trong bất kỳ hoạt động nào.