โมเดลวัตถุหน้าและโรงงานใน Selenium
⚡ สรุปอย่างชาญฉลาด
โมเดลวัตถุหน้าและโรงงานหน้าใน Selenium กำหนดรูปแบบการออกแบบที่มีโครงสร้างสำหรับการสร้างกรอบการทำงานอัตโนมัติสำหรับการทดสอบที่แข็งแกร่งและบำรุงรักษาได้ โดยเน้นการสร้างคลาสเฉพาะหน้าซึ่งรวม WebElements และพฤติกรรมของพวกมันไว้ด้วยกัน ซึ่งจะช่วยลดความซ้ำซ้อนและปรับปรุงความสามารถในการอ่านและปรับขนาดของ Selenium สคริปต์ทดสอบ

Page Object Model คืออะไร และมีส่วนประกอบหลักอะไรบ้าง
โมเดลออบเจ็กต์เพจ (POM) เป็นรูปแบบการออกแบบที่นิยมใช้กันในการทดสอบระบบอัตโนมัติ ซึ่งสร้าง Object Repository สำหรับองค์ประกอบ UI บนเว็บ ข้อดีของโมเดลนี้คือช่วยลดความซ้ำซ้อนของโค้ดและปรับปรุงการบำรุงรักษาการทดสอบ
ภายใต้โมเดลนี้ สำหรับแต่ละหน้าเว็บในแอปพลิเคชัน ควรมีคลาส Page ที่สอดคล้องกัน คลาส Page นี้จะระบุ WebElements ของหน้าเว็บนั้น และยังประกอบด้วยเมธอด Page ที่ดำเนินการกับ WebElements เหล่านั้นด้วย ชื่อของเมธอดเหล่านี้ควรกำหนดตามงานที่กำลังดำเนินการอยู่ เช่น หากตัวโหลดกำลังรอให้เกตเวย์การชำระเงินปรากฏขึ้น ชื่อเมธอด POM อาจเป็น waitForPaymentScreenDisplay()
ส่วนประกอบหลักของโมเดลวัตถุหน้า
- คลาสหน้า: แสดงแต่ละหน้าเว็บเป็นคลาสที่แยกจากกัน
- ตัวระบุตำแหน่ง: ระบุองค์ประกอบเว็บโดยใช้ ID, XPath หรือตัวเลือก CSS
- วิธีการ: ประกอบด้วยการดำเนินการหรือการดำเนินการที่ดำเนินการบนองค์ประกอบ .page
- การนำกลับมาใช้ใหม่: Promoการนำรหัส TES มาใช้ซ้ำและการบำรุงรักษาที่ง่ายขึ้นในทุกการทดสอบ
- การแยกข้อกังวล: รักษาโครงสร้างหน้าให้เป็นอิสระจากตรรกะการทดสอบเพื่อการจัดระเบียบที่ดีขึ้น
ทำไมต้องใช้โมเดลออบเจ็กต์เพจ?
การเริ่มต้นระบบอัตโนมัติ UI ใน Selenium ไดรเวอร์เว็บ ไม่ใช่เรื่องยาก คุณเพียงแค่ต้องค้นหาองค์ประกอบและดำเนินการกับมัน
พิจารณาสคริปต์ง่ายๆ นี้เพื่อเข้าสู่ระบบเว็บไซต์
อย่างที่คุณเห็น สิ่งที่เราทำคือการค้นหาองค์ประกอบและเติมค่าให้กับองค์ประกอบเหล่านั้น
นี่เป็นสคริปต์ที่ใช้เวลานานและมักเกิดข้อผิดพลาด ในตอนแรกดูเหมือนจะง่าย แต่เมื่อชุดทดสอบขยายตัว การจัดการการเปลี่ยนแปลงองค์ประกอบก็กลายเป็นเรื่องยาก แต่เมื่อเวลาผ่านไป ชุดทดสอบก็จะขยายใหญ่ขึ้น เมื่อคุณเพิ่มบรรทัดในโค้ดมากขึ้นเรื่อยๆ สิ่งต่างๆ ก็จะยากขึ้น
ปัญหาหลักในการบำรุงรักษาสคริปต์ก็คือ หากมีสคริปต์ที่แตกต่างกัน 10 สคริปต์ใช้องค์ประกอบของหน้าเดียวกัน หากมีการเปลี่ยนแปลงในองค์ประกอบนั้น คุณจะต้องเปลี่ยนสคริปต์ทั้ง 10 สคริปต์ ซึ่งใช้เวลานานและเกิดข้อผิดพลาดได้ง่าย
วิธีที่ดีกว่าในการบำรุงรักษาสคริปต์คือการสร้างไฟล์คลาสแยกต่างหากที่จะค้นหาองค์ประกอบเว็บ เติมข้อมูล หรือตรวจสอบองค์ประกอบเหล่านั้น คลาสนี้สามารถนำกลับมาใช้ซ้ำในสคริปต์ทดสอบหลายตัวที่โต้ตอบกับองค์ประกอบเดียวกันได้ ในอนาคต หากมีการเปลี่ยนแปลงองค์ประกอบเว็บ เราจำเป็นต้องทำการเปลี่ยนแปลงในไฟล์คลาสเพียงไฟล์เดียว ไม่ใช่สคริปต์ 10 สคริปต์ที่แตกต่างกัน
วิธีการนี้เรียกว่า Page Object Model in Selenium. ช่วยให้โค้ดอ่านง่ายขึ้น บำรุงรักษาง่ายขึ้น และนำกลับมาใช้ซ้ำได้
👉 สมัครเรียนสดฟรี Selenium โครงการ
ข้อดีของ POM
- รูปแบบการออกแบบวัตถุในหน้าเพจระบุว่าการดำเนินการและโฟลว์ใน UI ควรแยกออกจากการตรวจสอบ แนวคิดนี้ทำให้โค้ดของเราสะอาดขึ้นและเข้าใจง่ายขึ้น
- ประโยชน์ประการที่สองคือ ที่เก็บอ็อบเจ็กต์นั้นเป็นอิสระจากกรณีทดสอบ ดังนั้นเราจึงสามารถใช้ที่เก็บอ็อบเจ็กต์เดียวกันสำหรับวัตถุประสงค์ที่แตกต่างกันด้วยเครื่องมือที่แตกต่างกัน ตัวอย่างเช่น เราสามารถผสานรวม Page Object Model เข้ากับ Selenium สีสดสวย TestNG/JUnit สำหรับการทำงาน การทดสอบ และในเวลาเดียวกันกับ JBehave/Cucumber สำหรับการทดสอบการยอมรับ
- Code มีประสิทธิภาพและเหมาะสมยิ่งขึ้นเนื่องจากมีการนำเมธอดของเพจมาใช้ซ้ำในคลาส POM
- วิธีการได้รับชื่อที่สมจริงมากขึ้นซึ่งสามารถแมปไปยังการดำเนินการที่เกิดขึ้นใน UI ได้อย่างง่ายดาย เช่น หากหลังจากคลิกปุ่มแล้วเราลงจอดบนหน้าแรก ชื่อวิธีการจะเป็นเช่น 'gotoHomePage()'
วิธีการนำ POM มาใช้ Selenium?
PLog ง่ายๆ ในโครงสร้างพื้นฐานของกรอบงาน Page Object Model โดยที่ whereManagereIDElements ของ AUT และวิธีการที่ดำเนินการกับองค์ประกอบเว็บเหล่านี้จะถูกเก็บรักษาไว้ภายในไฟล์ clog งานเช่นการตรวจสอบควรแยกออกจากกันเป็นส่วนหนึ่งของวิธีการทดสอบ
ตัวอย่างที่สมบูรณ์
กรณีทดสอบ: ไปที่ Guru99 เว็บไซต์สาธิต
ขั้นตอนที่ 1) ไปที่ Guru99 เว็บไซต์สาธิต
ขั้นตอนที่ 2) บนหน้าแรก ตรวจสอบว่าข้อความ “Guru"ธนาคาร 99" มีอยู่
ขั้นตอนที่ 3) เข้าสู่ระบบแอปพลิเคชัน
ขั้นตอนที่ 4) ตรวจสอบว่าหน้าแรกมีข้อความเป็น “Manger Id: demo”
ในตัวอย่างนี้ เราจะจัดการกับสองหน้า:
- เข้าสู่ระบบหน้า
- หน้าแรก (แสดงเมื่อคุณเข้าสู่ระบบ)
ดังนั้นเราจึงสร้าง POM 2 อันขึ้นมา Selenium ชั้นเรียน
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 the 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 allows the test case to perform the login operation
* @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();
}
}
Guru99 หน้าแรก POM ใน 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 แบบง่ายใน Selenium กรณีทดสอบ
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("https://demo.guru99.com/V4/");
}
/**
* This test case will login in https://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("manager id : mgr123"));
}
Page Factory คืออะไร Selenium?
หน้าโรงงานใน Selenium เป็นแนวคิดเฟรมเวิร์ก Page Object Model แบบ inbuilt สำหรับ Selenium WebDriver ที่ปรับปรุงความสามารถในการบำรุงรักษาโดยลดการค้นหาองค์ประกอบซ้ำๆ โดยใช้คำอธิบายประกอบ ไม่ใช่ความเร็วในการทำงาน ใช้สำหรับการเริ่มต้นอ็อบเจ็กต์ Page หรือสร้างอินสแตนซ์ของอ็อบเจ็กต์ Page เอง นอกจากนี้ยังใช้สำหรับการเริ่มต้นองค์ประกอบคลาส Page โดยไม่ต้องใช้ "FindElement/s"
ในที่นี้ เรายังปฏิบัติตามแนวคิดของการแยก Page Object Repository และ Test Methods นอกจากนี้ด้วยความช่วยเหลือของคลาส PageFactory ใน Seleniumเราใช้คำอธิบายประกอบ @FindBy เพื่อค้นหา WebElement เราใช้วิธี initElements เพื่อเริ่มต้นองค์ประกอบเว็บ
@FindBy ยอมรับได้ tagName, PartialLinkText, ชื่อ, linkText, id, css, className, xpath เป็นคุณลักษณะ
ลองดูตัวอย่างเดียวกันกับข้างบนโดยใช้ Page Factory
Guru99 หน้าเข้าสู่ระบบด้วย 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();
}
}
Guru99 หน้าแรกด้วย 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 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 กรณีทดสอบด้วยแนวคิด 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("https://demo.guru99.com/V4/");
}
/**
* This test go to https://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("manager id : mgr123"));
}
}
โครงสร้างโครงการที่สมบูรณ์จะมีลักษณะเหมือนแผนภาพ:
โรงงาน AjaxElementLocator
โรงงาน AjaxElementLocator เป็นแนวคิดการโหลดแบบ Lazy Loading ของ PageFactory ใน Seleniumใช้เพื่อค้นหาองค์ประกอบเว็บเฉพาะเมื่อองค์ประกอบนั้นถูกใช้ในการดำเนินการใดๆ เท่านั้น โดยจะกำหนดเวลาหมดเวลาสำหรับ WebElements ให้กับคลาสเพจของอ็อบเจ็กต์ ข้อดีหลักประการหนึ่งของการใช้รูปแบบ PageFactory ใน Selenium เป็นคลาส AjaxElementLocatorFactory
ในกรณีนี้ เมื่อดำเนินการกับองค์ประกอบ การรอให้องค์ประกอบนั้นปรากฏจะเริ่มตั้งแต่วินาทีนั้นเท่านั้น หากไม่พบองค์ประกอบนั้นภายในช่วงเวลาที่กำหนด กรณีทดสอบ การดำเนินการจะส่งข้อยกเว้น 'NoSuchElementException'
ตัวอย่างเช่น:
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 10); PageFactory.initElements(factory, this);
ดาวน์โหลด Selenium ไฟล์โครงการสำหรับการสาธิตในบทช่วยสอนนี้











