page object model with page factory selenium tutorial
이 심층 자습서에서는 예제를 사용하여 Pagefactory를 사용하여 POM (페이지 개체 모델)에 대한 모든 것을 설명합니다. 또한 Selenium에서 POM 구현을 배울 수 있습니다.
이 자습서에서는 페이지 팩토리 접근 방식을 사용하여 페이지 개체 모델을 만드는 방법을 이해합니다. 우리는 다음에 초점을 맞출 것입니다.
- 공장 클래스
- 페이지 팩토리 패턴을 사용하여 기본 POM을 만드는 방법
- 페이지 팩토리 접근 방식에 사용되는 다양한 주석
Pagefactory가 무엇이고 페이지 개체 모델과 함께 사용되는 방법을보기 전에 일반적으로 POM으로 알려진 페이지 개체 모델이 무엇인지 이해하겠습니다.
=> 모두를위한 셀레늄 교육 시리즈를 보려면 여기를 방문하십시오.
학습 내용 :
페이지 개체 모델 (POM)이란?
이론적 용어는 페이지 개체 모델 테스트중인 애플리케이션에서 사용할 수있는 웹 요소에 대한 개체 저장소를 구축하는 데 사용되는 디자인 패턴입니다. 테스트중인 애플리케이션에 대해 Selenium 자동화를위한 프레임 워크로 언급하는 사람은 거의 없습니다.
그러나 페이지 개체 모델이라는 용어에 대해 이해 한 것은 다음과 같습니다.
#1) 애플리케이션의 각 화면 또는 페이지에 해당하는 별도의 Java 클래스 파일이있는 디자인 패턴입니다. 클래스 파일에는 UI 요소의 개체 저장소와 메서드가 포함될 수 있습니다.
#두) 페이지에 방대한 웹 요소가있는 경우 페이지에 대한 개체 저장소 클래스는 해당 페이지에 대한 메서드를 포함하는 클래스와 분리 될 수 있습니다.
예: 계정 등록 페이지에 많은 입력 필드가있는 경우 계정 등록 페이지에서 UI 요소에 대한 오브젝트 저장소를 형성하는 RegisterAccountObjects.java 클래스가있을 수 있습니다.
페이지에서 다른 작업을 수행하는 모든 메서드를 포함하는 RegisterAccountObjects를 확장하거나 상속하는 별도의 클래스 파일 RegisterAccount.java를 만들 수 있습니다.
#삼) 게다가 패키지 아래에 {속성 파일, 엑셀 테스트 데이터, 공통 메소드가있는 일반 패키지가있을 수 있습니다.
예: 응용 프로그램의 모든 페이지에서 매우 쉽게 사용할 수있는 DriverFactory
예제로 POM 이해
검사 여기 POM에 대해 자세히 알아보십시오.
다음은 웹 페이지의 스냅 샷입니다.
이러한 각 링크를 클릭하면 사용자가 새 페이지로 리디렉션됩니다.
다음은 웹 사이트의 각 페이지에 해당하는 페이지 개체 모델을 사용하여 Selenium으로 프로젝트 구조를 구축하는 방법에 대한 스냅 샷입니다. 모든 Java 클래스에는 페이지 내에서 다양한 작업을 수행하기위한 객체 저장소 및 메소드가 포함되어 있습니다.
게다가 이러한 페이지의 클래스 파일에 대한 호출을 호출하는 다른 JUNIT 또는 TestNG 또는 Java 클래스 파일이 있습니다.
페이지 개체 모델을 사용하는 이유는 무엇입니까?
POM 또는 페이지 개체 모델이라고하는이 강력한 Selenium 프레임 워크의 사용에 대한 소문이 있습니다. 이제 '왜 POM을 사용합니까?'라는 질문이 제기됩니다.
이에 대한 간단한 대답은 POM이 데이터 기반, 모듈 식 및 하이브리드 프레임 워크의 조합이라는 것입니다. 이는 QA가 번거 로움없이 코드를 쉽게 유지 관리하고 중복 또는 중복 코드를 방지하는 데 도움이되는 방식으로 스크립트를 체계적으로 구성하는 접근 방식입니다.
예를 들어 특정 페이지의 로케이터 값이 변경된 경우 다른 곳의 코드에 영향을주지 않고 각 페이지의 스크립트에서만 신속하게 변경하고 식별하는 것이 매우 쉽습니다.
다음과 같은 이유로 Selenium Webdriver에서 페이지 개체 모델 개념을 사용합니다.
- 이 POM 모델에서 개체 저장소가 생성됩니다. 테스트 케이스와 독립적이며 다른 프로젝트에 재사용 할 수 있습니다.
- 메서드의 명명 규칙은 매우 쉽고 이해하기 쉽고 현실적입니다.
- Page 개체 모델에서 다른 프로젝트에서 재사용 할 수있는 페이지 클래스를 만듭니다.
- 페이지 개체 모델은 몇 가지 장점으로 인해 개발 된 프레임 워크에서 사용하기 쉽습니다.
- 이 모델에서는 로그인 페이지, 홈 페이지, 직원 세부 정보 페이지, 비밀번호 변경 페이지 등과 같은 웹 애플리케이션의 여러 페이지에 대해 별도의 클래스가 생성됩니다.
- 웹 사이트의 요소가 변경된 경우 모든 클래스가 아닌 한 클래스 만 변경하면됩니다.
- 디자인 된 스크립트는 페이지 개체 모델 접근 방식에서 더 재사용, 읽기 및 유지 관리가 가능합니다.
- 프로젝트 구조는 매우 쉽고 이해하기 쉽습니다.
- 웹 요소를 초기화하고 캐시에 요소를 저장하기 위해 페이지 개체 모델에서 PageFactory를 사용할 수 있습니다.
- TestNG는 페이지 개체 모델 접근 방식에 통합 될 수도 있습니다.
셀레늄에서 단순 POM 구현
# 1) 자동화 할 시나리오
이제 페이지 개체 모델을 사용하여 주어진 시나리오를 자동화합니다.
시나리오는 아래에 설명되어 있습니다.
1 단계: 'https : //demo.vtiger.com'사이트를 시작합니다.
2 단계: 유효한 자격 증명을 입력하십시오.
3 단계 : 사이트에 로그인하십시오.
4 단계 : 홈 페이지를 확인하십시오.
5 단계 : 사이트에서 로그 아웃합니다.
6 단계 : 브라우저를 닫습니다.
# 2) POM의 위 시나리오를위한 셀레늄 스크립트
이제 아래에 설명 된대로 Eclipse에서 POM 구조를 만듭니다.
1 단계: Eclipse에서 프로젝트 만들기 – POM 기반 구조 :
a) 프로젝트“페이지 개체 모델”을 만듭니다.
b) 프로젝트 아래에 3 개의 패키지를 생성합니다.
- 도서관
- 페이지
- 테스트 케이스
도서관: 이 아래에 브라우저 실행, 스크린 샷 등과 같은 테스트 케이스에 계속해서 호출해야하는 코드를 넣습니다. 사용자는 프로젝트 필요에 따라 더 많은 클래스를 추가 할 수 있습니다.
페이지 : 여기에서 웹 애플리케이션의 각 페이지에 대해 클래스가 생성되고 애플리케이션의 페이지 수에 따라 더 많은 페이지 클래스를 추가 할 수 있습니다.
테스트 사례 : 이 아래에서 로그인 테스트 케이스를 작성하고 전체 애플리케이션을 테스트하는 데 필요한만큼 더 많은 테스트 케이스를 추가 할 수 있습니다.
c) 패키지 아래의 클래스는 아래 이미지와 같습니다.
단계 두: 라이브러리 패키지 아래에 다음 클래스를 만듭니다.
Browser.java : 이 클래스에서는 3 개의 브라우저 (Firefox, Chrome, Internet Explorer)를 정의하고 로그인 테스트 케이스에서 호출합니다. 요구 사항에 따라 사용자는 다른 브라우저에서도 응용 프로그램을 테스트 할 수 있습니다.
package library; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.ie.InternetExplorerDriver; public class Browser { static WebDriver driver; public static WebDriver StartBrowser(String browsername , String url) { // If the browser is Firefox if (browsername.equalsIgnoreCase('Firefox')) { // Set the path for geckodriver.exe System.setProperty('webdriver.firefox.marionette',' E://Selenium//Selenium_Jars//geckodriver.exe '); driver = new FirefoxDriver(); } // If the browser is Chrome else if (browsername.equalsIgnoreCase('Chrome')) { // Set the path for chromedriver.exe System.setProperty('webdriver.chrome.driver','E://Selenium//Selenium_Jars//chromedriver.exe'); driver = new ChromeDriver(); } // If the browser is IE else if (browsername.equalsIgnoreCase('IE')) { // Set the path for IEdriver.exe System.setProperty('webdriver.ie.driver','E://Selenium//Selenium_Jars//IEDriverServer.exe'); driver = new InternetExplorerDriver(); } driver.manage().window().maximize(); driver.get(url); return driver; } }
ScreenShot.java : 이 클래스에서는 스크린 샷 프로그램이 작성되고 사용자가 테스트 실패 또는 통과 여부에 대한 스크린 샷을 찍고 자 할 때 테스트 케이스에서 호출됩니다.
package library; import java.io.File; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; public class ScreenShot { public static void captureScreenShot(WebDriver driver, String ScreenShotName) { try { File screenshot=((TakesScreenshot)driver).getScreenshotAs(OutputType. FILE ); FileUtils.copyFile(screenshot, new File('E://Selenium//'+ScreenShotName+'.jpg')); } catch (Exception e) { System. out .println(e.getMessage()); e.printStackTrace(); } } }
3 단계 : 페이지 패키지 아래에 페이지 클래스를 만듭니다.
HomePage.java : 홈 페이지의 모든 요소와 메소드가 정의 된 홈 페이지 클래스입니다.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; By logout = By.id('p_lt_ctl03_wSOB_btnSignOutLink'); By home = By.id('p_lt_ctl02_wCU2_lblLabel'); //Constructor to initialize object public HomePage(WebDriver dr) { this .driver=dr; } public String pageverify() { return driver.findElement(home).getText(); } public void logout() { driver.findElement(logout).click(); } }
LoginPage.java : 로그인 페이지의 모든 요소와 메소드가 정의 된 로그인 페이지 클래스입니다.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class LoginPage { WebDriver driver; By UserID = By.xpath('//*(contains(@id,'Login1_UserName'))'); By password = By.xpath('//*(contains(@id,'Login1_Password'))'); By Submit = By.xpath('//*(contains(@id,'Login1_LoginButton'))'); //Constructor to initialize object public LoginPage(WebDriver driver) { this .driver = driver; } public void loginToSite(String Username, String Password) { this .enterUsername(Username); this .enterPasssword(Password); this .clickSubmit(); } public void enterUsername(String Username) { driver.findElement(UserID).sendKeys(Username); } public void enterPasssword(String Password) { driver.findElement(password).sendKeys(Password); } public void clickSubmit() { driver.findElement(Submit).click(); } }
4 단계 : 로그인 시나리오에 대한 테스트 케이스를 작성하십시오.
LoginTestCase.java : 이것은 테스트 케이스가 실행되는 LoginTestCase 클래스입니다. 사용자는 프로젝트 요구에 따라 더 많은 테스트 케이스를 만들 수도 있습니다.
package testcases; import java.util.concurrent.TimeUnit; import library.Browser; import library.ScreenShot; import org.openqa.selenium.WebDriver; import org.testng.Assert; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.HomePage; import pages.LoginPage; public class LoginTestCase { WebDriver driver; LoginPage lp; HomePage hp; int i = 0; // Launch of the given browser. @BeforeTest public void browserlaunch() { driver = Browser.StartBrowser('Chrome', 'http://demostore.kenticolab.com/Special-Pages/Logon.aspx'); driver.manage().timeouts().implicitlyWait(30,TimeUnit. SECONDS ); lp = new LoginPage(driver); hp = new HomePage(driver); } // Login to the Site. @Test(priority = 1) public void Login() { lp.loginToSite('gaurav.3n@gmail.com','Test@123'); } // Verifing the Home Page. @Test(priority = 2) public void HomePageVerify() { String HomeText = hp.pageverify(); Assert.assertEquals(HomeText, 'Logged on as'); } // Logout the site. @Test(priority = 3) public void Logout() { hp.logout(); } // Taking Screen shot on test fail @AfterMethod public void screenshot(ITestResult result) { i = i+1; String name = 'ScreenShot'; String x = name+String.valueOf(i); if (ITestResult. FAILURE == result.getStatus()) { ScreenShot.captureScreenShot(driver, x); } } @AfterTest public void closeBrowser() { driver.close(); } }
5 단계 : 'LoginTestCase.java'를 실행합니다.
6 단계 : 페이지 개체 모델의 출력 :
- Chrome 브라우저를 시작합니다.
- 데모 웹 사이트가 브라우저에서 열립니다.
- 데모 사이트에 로그인하십시오.
- 홈페이지를 확인하십시오.
- 사이트에서 로그 아웃합니다.
- 브라우저를 닫습니다.
이제 관심을 끄는이 튜토리얼의 주요 개념을 살펴 보겠습니다. “Pagefactory”.
Pagefactory는 무엇입니까?
PageFactory는 '페이지 개체 모델'을 구현하는 방법입니다. 여기서는 페이지 개체 저장소와 테스트 방법의 분리 원칙을 따릅니다. 매우 최적화 된 페이지 개체 모델의 내장 된 개념입니다.
이제 Pagefactory라는 용어에 대해 더 명확하게하겠습니다.
#1) 첫째, Pagefactory라는 개념은 페이지의 웹 요소에 대한 개체 저장소를 생성하기위한 구문 및 의미 측면에서 대체 방법을 제공합니다.
#두) 둘째, 웹 요소 초기화에 약간 다른 전략을 사용합니다.
#삼) UI 웹 요소의 객체 저장소는 다음을 사용하여 빌드 할 수 있습니다.
- 일반적인‘Pagefactory없는 POM’과
- 또는 'Pagefactory와 함께 POM'을 사용할 수 있습니다.
다음은 동일한 그림 표현입니다.
이제 Pagefactory를 사용하여 일반적인 POM과 POM을 차별화하는 모든 측면을 살펴 보겠습니다.
a) Pagefactory를 사용하는 POM과 일반적인 POM을 사용하여 요소를 찾는 구문의 차이.
예를 들어 , 클릭 여기 페이지에 표시되는 검색 필드를 찾습니다.
Pagefactory가없는 POM :
# 1) 다음은 일반적인 POM을 사용하여 검색 필드를 찾는 방법입니다.
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) 아래 단계는 Search NSE 필드에 'investment'값을 전달합니다.
searchNSETxt.sendkeys(“investment”);
Pagefactory를 사용하는 POM :
#1) 아래와 같이 Pagefactory를 사용하여 검색 필드를 찾을 수 있습니다.
주석 @FindBy Pagefactory에서 요소를 식별하기 위해 사용되는 반면 Pagefactory가없는 POM은 driver.findElement () 요소를 찾는 방법.
Pagefactory에 대한 두 번째 진술은 @FindBy 유형을 할당하고 있습니다. WebElement 메소드의 반환 유형으로 WebElement 클래스 유형의 요소 이름 할당과 정확히 유사하게 작동하는 클래스 driver.findElement () 일반적인 POM에서 사용됩니다 (이 예에서는 searchNSETxt).
우리는 @FindBy 이 자습서의 다음 부분에서 자세히 설명합니다.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
#두) 아래 단계에서는 'investment'값을 NSE 검색 필드에 전달하고 구문은 일반 POM (Pagefactory없는 POM)의 구문과 동일하게 유지됩니다.
searchNSETxt.sendkeys(“investment”);
b) 일반적인 POM을 사용하는 웹 요소 초기화 전략과 Pagefactory를 사용하는 POM의 차이.
Pagefactory없이 POM 사용 :
다음은 Chrome 드라이버 경로를 설정하는 코드 스 니펫입니다. WebDriver 인스턴스는 driver라는 이름으로 생성되고 ChromeDriver는 '드라이버'에 할당됩니다. 그런 다음 동일한 드라이버 개체를 사용하여 National Stock Exchange 웹 사이트를 시작하고 searchBox를 찾은 다음 필드에 문자열 값을 입력합니다.
여기서 강조하고 싶은 점은 페이지 팩토리가없는 POM 일 때 드라이버 인스턴스가 처음에 생성되고 driver.findElement () 또는 driver를 사용하여 해당 웹 요소를 호출 할 때마다 모든 웹 요소가 새로 초기화된다는 것입니다. .findElements ().
이것이 요소에 대한 driver.findElement ()의 새로운 단계를 통해 DOM 구조를 다시 스캔하고 해당 페이지에서 요소의 새로 고침 식별이 수행되는 이유입니다.
System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automationframework\src\test\java\Drivers\chromedriver.exe'); WebDriver driver = new ChromeDriver(); driver.get('http://www.nseindia.com/'); WebElement searchNSETxt=driver.findElement(By.id(“searchBox”)); searchNSETxt.sendkeys(“investment”);
Pagefactory와 함께 POM 사용 :
driver.findElement () 메서드 대신 @FindBy 주석을 사용하는 것 외에도 아래 코드 조각이 Pagefactory에 추가로 사용됩니다. PageFactory 클래스의 정적 initElements () 메서드는 페이지가로드되는 즉시 페이지의 모든 UI 요소를 초기화하는 데 사용됩니다.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
위의 전략은 PageFactory 접근 방식을 일반적인 POM과 약간 다릅니다. 일반적인 POM에서는 웹 요소를 명시 적으로 초기화해야하며 Pagefactory 접근 방식에서는 모든 요소가 각 웹 요소를 명시 적으로 초기화하지 않고 initElements ()로 초기화됩니다.
예를 들면 : WebElement가 선언되었지만 일반적인 POM에서 초기화되지 않은 경우 'initialize variable'오류 또는 NullPointerException이 발생합니다. 따라서 일반적인 POM에서는 각 WebElement를 명시 적으로 초기화해야합니다. 이 경우 PageFactory는 일반적인 POM에 비해 이점이 있습니다.
웹 요소를 초기화하지 말자 BDate (Pagefactory가없는 POM) '변수 초기화'오류가 표시되고 사용자에게이를 null로 초기화하라는 메시지를 표시하는 것을 볼 수 있습니다. 따라서 요소를 찾을 때 암시 적으로 초기화된다고 가정 할 수 없습니다.
명시 적으로 초기화 된 요소 BDate (Pagefactory가없는 POM) :
이제 구현 측면을 이해하는 데있어 모호함을 배제하기 위해 PageFactory를 사용하는 완전한 프로그램의 몇 가지 인스턴스를 살펴 보겠습니다.
예 1 :
- ‘http://www.nseindia.com/’으로 이동합니다.
- 검색 필드 옆에있는 드롭 다운에서 'Currency Derivatives'를 선택합니다.
- ‘USDINR’을 검색합니다. 결과 페이지에서 'US Dollar-Indian Rupee – USDINR'텍스트를 확인합니다.
프로그램 구조 :
- 모든 웹 요소를 초기화하기위한 생성자 인 nseindia.com에 대한 페이지 팩토리 개념을 사용하는 객체 저장소를 포함하는 PagefactoryClass.java가 생성되고, selectCurrentDerivative () 메서드는 Searchbox 드롭 다운 필드에서 값을 선택하고 selectSymbol ()에서 기호를 선택합니다. 다음에 표시되는 페이지와 verifytext ()를 통해 페이지 헤더가 예상대로인지 확인합니다.
- NSE_MainClass.java는 위의 모든 메서드를 호출하고 NSE 사이트에서 해당 작업을 수행하는 기본 클래스 파일입니다.
PagefactoryClass.java
package com.pagefactory.knowledge; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.Select; public class PagefactoryClass { WebDriver driver; @FindBy(id = 'QuoteSearch') WebElement Searchbox; @FindBy(id = 'cidkeyword') WebElement Symbol; @FindBy(id = 'companyName') WebElement pageText; public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } public void selectCurrentDerivative(String derivative) { Select select = new Select(Searchbox); select.selectByVisibleText(derivative); // 'Currency Derivatives' } public void selectSymbol(String symbol) { Symbol.sendKeys(symbol); } public void verifytext() { if (pageText.getText().equalsIgnoreCase('U S Dollar-Indian Rupee - USDINR')) { System.out.println('Page Header is as expected'); } else System.out.println('Page Header is NOT as expected'); } }
NSE_MainClass.java
package com.pagefactory.knowledge; import java.util.List; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class NSE_MainClass { static PagefactoryClass page; static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\Users\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.nseindia.com/'); driver.manage().window().maximize(); test_Home_Page_ofNSE(); } public static void test_Home_Page_ofNSE() throws StaleElementReferenceException { page = new PagefactoryClass(driver); page.selectCurrentDerivative('Currency Derivatives'); page.selectSymbol('USD'); List Options = driver.findElements(By.xpath('//span(contains(.,'USD'))')); int count = Options.size(); for (int i = 0; i 예 2 :
- 'https://www.shoppersstop.com/brands'로 이동
- Haute curry 링크로 이동합니다.
- Haute Curry 페이지에 'Start New Something'텍스트가 포함되어 있는지 확인합니다.
프로그램 구조
- 모든 웹 요소를 초기화하기위한 생성자 인 shoppersstop.com에 대한 pagefactory 개념을 사용하는 객체 저장소를 포함하는 shopperstopPagefactory.java가 생성되고, 열리는 경고 팝업 상자를 처리하기위한 closeExtraPopup () 메소드, 클릭 OnHauteCurryLink ()를 클릭하여 Haute Curry를 클릭합니다. 링크 및 verifyStartNewSomething ()을 사용하여 Haute Curry 페이지에 'Start new something'이라는 텍스트가 있는지 확인합니다.
- Shopperstop_CallPagefactory.java는 위의 모든 메소드를 호출하고 NSE 사이트에서 해당 작업을 수행하는 기본 클래스 파일입니다.
shopperstopPagefactory.java
package com.inportia.automation_framework; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class shopperstopPagefactory { WebDriver driver; @FindBy(id='firstVisit') WebElement extrapopup; @FindBy(xpath='//img(@src='https://sslimages.shoppersstop.com /sys-master/root/haf/h3a/9519787376670/brandMedia_HauteCurry_logo.png')') WebElement HCLink; @FindBy(xpath='/html/body/main/footer/div(1)/p') WebElement Startnew; public shopperstopPagefactory(WebDriver driver) { this.driver=driver; PageFactory.initElements(driver, this); } public void closeExtraPopup() { extrapopup.click(); } public void clickOnHauteCurryLink() { JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript('arguments(0).click();',HCLink); js.executeAsyncScript('window.setTimeout(arguments(arguments.length - 1), 10000);'); if(driver.getCurrentUrl().equals('https://www.shoppersstop.com/haute-curry')) { System.out.println('We are on the Haute Curry page'); } else { System.out.println('We are NOT on the Haute Curry page'); } } public void verifyStartNewSomething() { if (Startnew.getText().equalsIgnoreCase('Start Something New')) { System.out.println('Start new something text exists'); } else System.out.println('Start new something text DOESNOT exists'); } }
Shopperstop_CallPagefactory.java
package com.inportia.automation_framework; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class Shopperstop_CallPagefactory extends shopperstopPagefactory { public Shopperstop_CallPagefactory(WebDriver driver) { super(driver); // TODO Auto-generated constructor stub } static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); Shopperstop_CallPagefactory s1=new Shopperstop_CallPagefactory(driver); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.shoppersstop.com/brands'); s1.clickOnHauteCurryLink(); s1.verifyStartNewSomething(); } }
페이지 팩토리를 사용하는 POM
비디오 튜토리얼 – POM with Page Factory
파트 I
파트 II
Factory 클래스는 페이지 개체를 더 간단하고 쉽게 사용하는 데 사용됩니다.
- 먼저 주석으로 웹 요소를 찾아야합니다. @FindBy 페이지 클래스 .
- 그런 다음 페이지 클래스를 인스턴스화 할 때 initElements ()를 사용하여 요소를 초기화하십시오.
#1) @FindBy :
@FindBy 주석은 PageFactory에서 다른 로케이터를 사용하여 웹 요소를 찾고 선언하는 데 사용됩니다.여기에서 웹 요소를 찾는 데 사용되는 속성과 해당 값을 @FindBy 주석에 전달한 다음 WebElement가 선언됩니다.
주석을 사용할 수있는 방법에는 두 가지가 있습니다.
예를 들면 :
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
그러나 전자는 WebElements를 선언하는 표준 방법입니다.
'어떻게' 클래스이며 ID, XPATH, CLASSNAME, LINKTEXT 등과 같은 정적 변수가 있습니다.
‘사용’ – 정적 변수에 값을 할당합니다.
위에서 예 , 'id'속성을 사용하여 웹 요소 'Email'을 찾았습니다. 마찬가지로 @FindBy 주석과 함께 다음 로케이터를 사용할 수 있습니다.
- className
- CSS
- 이름
- xpath
- tagName
- linkText
- partialLinkText
# 2) initElements () :
initElements는 @FindBy 주석에 의해 위치한 모든 웹 요소를 초기화하는 데 사용되는 PageFactory 클래스의 정적 메소드입니다. 따라서 Page 클래스를 쉽게 인스턴스화합니다.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
또한 POM이 OOPS 원칙을 따른다는 것을 이해해야합니다.
- WebElements는 개인 멤버 변수 (데이터 숨기기)로 선언됩니다.
- WebElements를 해당 메서드로 바인딩 (Encapsulation).
페이지 팩토리 패턴을 사용하여 POM을 만드는 단계
#1) 각 웹 페이지에 대해 별도의 Java 클래스 파일을 만듭니다.
#두) 각 Class에서 모든 WebElement는 변수로 선언 (annotation – @FindBy 사용)하고 initElement () 메소드를 사용하여 초기화해야합니다. 선언 된 WebElement는 액션 메서드에서 사용하기 위해 초기화되어야합니다.
#삼) 해당 변수에 대해 작동하는 해당 메소드를 정의하십시오.
간단한 시나리오의 예를 들어 보겠습니다.
- 애플리케이션의 URL을 엽니 다.
- 이메일 주소와 비밀번호 데이터를 입력합니다.
- 로그인 버튼을 클릭하십시오.
- 검색 페이지에서 성공적인 로그인 메시지를 확인하십시오.
페이지 레이어
여기에 2 페이지가 있습니다.
- 홈페이지 – URL을 입력 할 때 열리는 페이지와 로그인 할 데이터를 입력하는 페이지입니다.
- SearchPage – 로그인에 성공하면 표시되는 페이지입니다.
페이지 계층에서 웹 애플리케이션의 각 페이지는 별도의 Java 클래스로 선언되며 해당 위치 지정자 및 조치가 여기에 언급됩니다.
실시간 예제를 사용하여 POM을 만드는 단계
# 1) 각 페이지에 대한 Java 클래스를 만듭니다.
이것에 예 , 우리는 2 개의 웹 페이지, '홈'및 '검색'페이지에 액세스합니다.
따라서 페이지 계층 (또는 패키지에서 com.automation.pages)에 2 개의 Java 클래스를 생성합니다.
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) @FindBy 주석을 사용하여 WebElement를 변수로 정의합니다.
우리는 다음과 상호 작용할 것입니다.
- 홈 페이지의 이메일, 비밀번호, 로그인 버튼 필드.
- 검색 페이지의 성공 메시지입니다.
따라서 @FindBy를 사용하여 WebElements를 정의합니다.
예를 들면 : 속성 id를 사용하여 EmailAddress를 식별하려는 경우 변수 선언은 다음과 같습니다.
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) WebElements에서 수행되는 작업에 대한 메서드를 만듭니다.
WebElements에서 다음 작업이 수행됩니다.
- 이메일 주소 필드에 action을 입력하십시오.
- 암호 필드에 action을 입력하십시오.
- 로그인 버튼에서 작업을 클릭합니다.
예를 들어 WebElement의 각 작업에 대해 다음과 같이 사용자 정의 메서드가 생성됩니다.
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
여기서 Id는 기본 테스트 케이스에서 사용자가 입력을 보내므로 메서드의 매개 변수로 전달됩니다.
노트 :테스트 레이어의 Main 클래스에서 드라이버 인스턴스를 가져오고 PageFactory.InitElement ()를 사용하여 페이지 클래스에 선언 된 WebElements (Page Objects)를 초기화하려면 페이지 레이어의 각 클래스에 생성자를 만들어야합니다. .
여기서는 드라이버를 시작하지 않고 페이지 계층 클래스의 개체가 생성 될 때 기본 클래스에서 해당 인스턴스를받습니다.
InitElement () – 기본 클래스의 드라이버 인스턴스를 사용하여 선언 된 WebElements를 초기화하는 데 사용됩니다. 즉, WebElement는 드라이버 인스턴스를 사용하여 생성됩니다. WebElements가 초기화 된 후에 만 메서드에서 작업을 수행하는 데 사용할 수 있습니다.
다음과 같이 각 페이지에 대해 두 개의 Java 클래스가 생성됩니다.
HomePage.java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; // Locator for Email Address @FindBy(how=How.ID,using='EmailId') private WebElement EmailIdAddress; // Locator for Password field @FindBy(how=How.ID,using='Password ') private WebElement Password; // Locator for SignIn Button @FindBy(how=How.ID,using='SignInButton') private WebElement SignInButton; // Method to type EmailId public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) } // Method to type Password public void typePassword(String PasswordValue){ driver.findElement(Password).sendKeys(PasswordValue) } // Method to click SignIn Button public void clickSignIn(){ driver.findElement(SignInButton).click() } // Constructor // Gets called when object of this page is created in MainClass.java public HomePage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
SearchPage.Java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class SearchPage{ WebDriver driver; // Locator for Success Message @FindBy(how=How.ID,using='Message') private WebElement SuccessMessage; // Method that return True or False depending on whether the message is displayed public Boolean MessageDisplayed(){ Boolean status = driver.findElement(SuccessMessage).isDisplayed(); return status; } // Constructor // This constructor is invoked when object of this page is created in MainClass.java public SearchPage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
테스트 레이어
테스트 케이스는이 클래스에서 구현됩니다. com.automation.test라는 별도의 패키지를 만든 다음 여기에 Java 클래스 (MainClass.java)를 만듭니다.
테스트 케이스를 만드는 단계 :
- 드라이버를 초기화하고 응용 프로그램을 엽니 다.
- 각 웹 페이지에 대해 PageLayer 클래스의 개체를 만들고 드라이버 인스턴스를 매개 변수로 전달합니다.
- 생성 된 객체를 사용하여 작업 / 검증을 수행하기 위해 PageLayer 클래스 (각 웹 페이지에 대해)의 메소드를 호출합니다.
- 모든 작업이 수행 될 때까지 3 단계를 반복 한 다음 드라이버를 닫습니다.
//package com.automation.test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class MainClass { public static void main(String() args) { System.setProperty('webdriver.chrome.driver','./exefiles/chromedriver.exe'); WebDriver driver= new ChromeDriver(); driver.manage().window().maximize(); driver.get('URL mentioned here'); // Creating object of HomePage and driver instance is passed as parameter to constructor of Homepage.Java HomePage homePage= new HomePage(driver); // Type EmailAddress homePage.typeEmailId('abc@ymail.com'); // EmailId value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Type Password Value homePage.typePassword('password123'); // Password value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Click on SignIn Button homePage.clickSignIn(); // Creating an object of LoginPage and driver instance is passed as parameter to constructor of SearchPage.Java SearchPage searchPage= new SearchPage(driver); //Verify that Success Message is displayed Assert.assertTrue(searchPage.MessageDisplayed()); //Quit browser driver.quit(); } }
WebElements 선언에 사용되는 주석 유형 계층
주석은 UI 요소에 대한 위치 전략을 구성하는 데 사용됩니다.
# 1) @FindBy
Pagefactory와 관련하여 @FindBy는 마법의 지팡이 역할을합니다. 그것은 개념에 모든 힘을 더합니다. 이제 Pagefactory의 @FindBy 주석이 일반적인 페이지 개체 모델의 driver.findElement () 주석과 동일하게 수행된다는 것을 알고 있습니다. WebElement / WebElements를 찾는 데 사용됩니다. 하나의 기준으로 .
# 2) @FindBys
WebElement를 찾는 데 사용됩니다. 하나 이상의 기준 주어진 모든 기준과 일치해야합니다. 이러한 기준은 부모-자녀 관계에서 언급되어야합니다. 즉, AND 조건부 관계를 사용하여 지정된 기준을 사용하여 WebElement를 찾습니다. 여러 @FindBy를 사용하여 각 기준을 정의합니다.
예를 들면 :
WebElement의 HTML 소스 코드 :
POM에서 :
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
위의 예에서 WebElement‘SearchButton’은 둘 다 일치 id 값이 'searchId_1'이고 이름 값이 'search_field'인 기준 첫 번째 기준은 상위 태그에 속하고 두 번째 기준은 하위 태그에 속합니다.
# 3) @FindAll
WebElement를 찾는 데 사용됩니다. 하나 이상의 기준 주어진 기준 중 하나 이상과 일치해야합니다. 이것은 WebElements를 찾기 위해 OR 조건부 관계를 사용합니다. 여러 @FindBy를 사용하여 모든 기준을 정의합니다.
예를 들면 :
HTML 소스 코드 :
POM에서 :
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
위의 예에서 WebElement‘Username은 적어도 하나와 일치 언급 된 기준의.
# 4) @CacheLookUp
WebElement가 테스트 케이스에서 더 자주 사용되면 Selenium은 테스트 스크립트가 실행될 때마다 WebElement를 찾습니다. 이러한 경우 특정 WebElements가 모든 TC ( 예를 들어 로그인 시나리오는 각 TC에 대해 발생합니다),이 주석은 처음으로 읽은 후 캐시 메모리에서 해당 WebElement를 유지하는 데 사용할 수 있습니다.
그러면 페이지에서 WebElement를 검색 할 필요가 없을 때마다 메모리에서 참조를 가져올 수 있으므로 코드를 더 빠르게 실행할 수 있습니다.
@FindBy, @FindBys 및 @FindAll의 접두사로 사용할 수 있습니다.
예를 들면 :
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
또한이 주석은 속성 값 (예 : xpath, id 이름, 클래스 이름 등)이 자주 변경되지 않는 WebElement에만 사용해야합니다. WebElement가 처음으로 발견되면 캐시 메모리에서 참조를 유지합니다.
따라서 며칠 후 WebElement의 속성이 변경되면 Selenium은 이미 캐시 메모리에 이전 참조가 있고 WebElement의 최근 변경 사항을 고려하지 않기 때문에 요소를 찾을 수 없습니다.
PageFactory.initElements ()에 대한 추가 정보
이제 InitElements ()를 사용하여 웹 요소를 초기화하는 Pagefactory의 전략을 이해 했으므로 다양한 버전의 메서드를 이해해 보겠습니다.
우리가 알고있는 메서드는 드라이버 개체와 현재 클래스 개체를 입력 매개 변수로 사용하고 페이지의 모든 요소를 암시 적으로 사전에 초기화하여 페이지 개체를 반환합니다.
실제로는 위 섹션에 표시된 생성자를 사용하는 것이 다른 사용 방법보다 더 바람직합니다.
메서드를 호출하는 다른 방법은 다음과 같습니다.
#1) 'this'포인터를 사용하는 대신 현재 클래스 객체를 생성하고 드라이버 인스턴스를 전달하고 매개 변수 (예 : 드라이버 객체 및 방금 생성 된 클래스 객체)를 사용하여 정적 메서드 initElements를 호출 할 수 있습니다.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
#두) Pagefactory 클래스를 사용하여 요소를 초기화하는 세 번째 방법은 'reflection'이라는 API를 사용하는 것입니다. 예, 'new'키워드를 사용하여 클래스 객체를 만드는 대신 classname.class를 initElements () 입력 매개 변수의 일부로 전달할 수 있습니다.
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
자주 묻는 질문
Q # 1) @FindBy에 사용되는 다른 로케이터 전략은 무엇입니까?
대답: 이에 대한 간단한 대답은 @FindBy에 사용되는 다른 로케이터 전략이 없다는 것입니다.
일반적인 POM의 findElement () 메소드가 사용하는 것과 동일한 8 개의 로케이터 전략을 사용합니다.
- 신분증
- 이름
- className
- xpath
- CSS
- tagName
- linkText
- partialLinkText
Q # 2) @FindBy 주석의 사용에도 다른 버전이 있습니까?
대답: 검색 할 웹 요소가있는 경우 @FindBy 주석을 사용합니다. 다른 로케이터 전략과 함께 @FindBy를 사용하는 다른 방법에 대해서도 자세히 설명하겠습니다.
우리는 이미 @FindBy 버전 1을 사용하는 방법을 보았습니다.
@FindBy(id = 'cidkeyword') WebElement Symbol;
@FindBy 버전 2는 입력 매개 변수를 다음과 같이 전달합니다. 어떻게 과 사용 .
어떻게 웹 요소를 식별 할 수있는 로케이터 전략을 찾습니다. 키워드 사용 로케이터 값을 정의합니다.
더 나은 이해를 위해 아래를 참조하십시오.
- How.ID는 신분증 전략과 식별하려는 요소에 id =가 있습니다. cidkeyword.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAME은 className 전략과 식별하려는 요소에는 class =가 있습니다. newclass.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
Q # 3) @FindBy의 두 버전간에 차이점이 있습니까?
대답: 대답은 아니오입니다. 두 버전간에 차이가 없습니다. 두 번째 버전에 비해 첫 번째 버전이 더 짧고 더 쉽습니다.
Q # 4) 찾을 웹 요소 목록이있는 경우 페이지 팩토리에서 무엇을 사용합니까?
대답: 일반적인 페이지 개체 디자인 패턴에서 동일한 클래스 또는 태그 이름에 속하는 여러 요소를 찾기 위해 driver.findElements ()가 있지만 Pagefactory를 사용하는 페이지 개체 모델의 경우 이러한 요소를 어떻게 찾습니까? 이러한 요소를 얻는 가장 쉬운 방법은 동일한 주석 @FindBy를 사용하는 것입니다.
저는이 대사가 많은 분들에게 머리를 긁는 것처럼 보인다는 것을 이해합니다. 그러나 네, 그것은 질문에 대한 답입니다.
아래 예를 살펴 보겠습니다.
Pagefactory없이 일반적인 페이지 개체 모델을 사용하면 driver.findElements를 사용하여 아래와 같이 여러 요소를 찾습니다.
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
아래와 같이 Pagefactory와 함께 페이지 개체 모델을 사용하여 동일한 결과를 얻을 수 있습니다.
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
기본적으로 WebElement 유형의 목록에 요소를 할당하면 요소를 식별하고 찾는 동안 Pagefactory가 사용되었는지 여부에 관계없이 트릭이 수행됩니다.
Q # 5) 페이지 팩토리가없는 페이지 객체 디자인과 페이지 팩토리가있는 페이지 객체 디자인을 동일한 프로그램에서 사용할 수 있습니까?
대답: 예, Pagefactory가없는 페이지 개체 디자인과 Pagefactory가있는 페이지 개체 디자인은 모두 동일한 프로그램에서 사용할 수 있습니다. 아래에 주어진 프로그램을 통해 갈 수 있습니다. 질문 # 6에 대한 답변 둘 다 프로그램에서 어떻게 사용되는지 확인하십시오.
기억해야 할 한 가지는 페이지 개체 디자인이 동적 요소에 대해 잘 작동하는 반면 캐시 된 기능이있는 Pagefactory 개념은 동적 요소에서 피해야한다는 것입니다. 그러나 Pagefactory는 정적 요소에만 적합합니다.
Q # 6) 여러 기준에 따라 요소를 식별하는 다른 방법이 있습니까?
안드로이드에 대한 무차별 암호 크래커 다운로드
대답: 여러 기준에 따라 요소를 식별하는 대안은 @FindAll 및 @FindBys 주석을 사용하는 것입니다. 이러한 주석은 전달 된 기준에서 가져온 값에 따라 단일 또는 다중 요소를 식별하는 데 도움이됩니다.
# 1) @FindAll :
@FindAll은 여러 @FindBy를 포함 할 수 있으며 단일 목록에서 @FindBy와 일치하는 모든 요소를 반환합니다. @FindAll은 조회가 일련의 @FindBy 태그를 사용해야 함을 나타 내기 위해 페이지 개체의 필드를 표시하는 데 사용됩니다. 그런 다음 FindBy 기준과 일치하는 모든 요소를 검색합니다.
요소가 문서 순서대로 보장되지는 않습니다.
@FindAll을 사용하는 구문은 다음과 같습니다.
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
설명: @FindAll은 @FindBy 기준 각각에 맞는 개별 요소를 검색하고 식별하여 나열합니다. 위의 예에서 먼저 id =”foo”인 요소를 검색 한 다음 className =”bar”로 두 번째 요소를 식별합니다.
각 FindBy 기준에 대해 식별 된 요소가 하나 있다고 가정하면 @FindAll은 각각 2 개의 요소를 나열합니다. 각 기준에 대해 식별 된 여러 요소가있을 수 있습니다. 따라서 간단히 말해서 @ 모두 찾기 다음과 같은 역할을합니다. 또는 @FindBy 기준에 대한 연산자가 전달되었습니다.
# 2) @FindBys :
FindBys는 페이지 개체의 필드를 표시하여 ByChained에 설명 된대로 체인에서 일련의 @FindBy 태그를 사용해야 함을 나타내는 데 사용됩니다. 필수 WebElement 개체가 지정된 모든 기준과 일치해야하는 경우 @FindBys 주석을 사용합니다.
@FindBys를 사용하는 구문은 다음과 같습니다.
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
설명: @FindBys는 모든 @FindBy 기준을 준수하는 요소를 검색하고 식별하여 나열합니다. 위의 예에서 이름 =”foo”및 className =”bar”인 요소를 검색합니다.
@FindAll은 주어진 기준에 이름과 className으로 식별 된 요소가 하나 있다고 가정하면 1 개의 요소를 나열합니다.
전달 된 모든 FindBy 조건을 충족하는 요소가 하나도 없으면 @FindBys의 결과는 0 요소가됩니다. 모든 조건이 여러 요소를 충족하는 경우 식별 된 웹 요소 목록이있을 수 있습니다. 간단히 말해서 @ FindBys 다음과 같은 역할을합니다. 과 @FindBy 기준에 대한 연산자가 전달되었습니다.
자세한 프로그램을 통해 위의 모든 주석의 구현을 살펴 보겠습니다.
@FindBy, @FindBys 및 @FindAll 주석의 구현을 이해하기 위해 이전 섹션에서 제공된 www.nseindia.com 프로그램을 수정합니다.
# 1) PagefactoryClass의 객체 저장소가 다음과 같이 업데이트됩니다.
목록 newlist = driver.findElements (By.tagName ( 'a'));
@FindBy (어떻게 = 어떻게. TAG_NAME , =“a”사용)
은밀한 findbyvalue 나열;
@FindAll ({ @FindBy (className =“sel”), @FindBy (xpath =”// a (@ id =’tab5 ′)”)})
은밀한 findallvalue 나열;
@FindBys ({ @FindBy (className =“sel”), @FindBy (xpath =”// a (@ id =’tab5 ′)”)})
은밀한 findbysvalue 나열;
# 2) 새 메소드 seeHowFindWorks ()가 PagefactoryClass에 작성되고 Main 클래스의 마지막 메소드로 호출됩니다.
방법은 다음과 같습니다.
private void seeHowFindWorks() { System.out.println('driver.findElements(By.tagName()) '+newlist.size()); System.out.println('count of @FindBy- list elements '+findbyvalue.size()); System.out.println('count of @FindAll elements '+findallvalue.size()); for(int i=0;i 다음은 프로그램 실행 후 콘솔 창에 표시되는 결과입니다.

이제 코드를 자세히 이해해 보겠습니다.
#1) 페이지 개체 디자인 패턴을 통해 'newlist'요소는 앵커 'a'가있는 모든 태그를 식별합니다. 즉, 페이지에있는 모든 링크의 수를 얻습니다.
pagefactory @FindBy가 driver.findElement ()와 동일한 작업을 수행한다는 것을 배웠습니다. findbyvalue 요소는 pagefactory 개념을 갖는 검색 전략을 통해 페이지의 모든 링크 수를 가져 오기 위해 작성됩니다.
driver.findElement () 및 @FindBy 모두 동일한 작업을 수행하고 동일한 요소를 식별하는 것이 옳다는 것을 증명합니다. 위의 결과 콘솔 창의 스크린 샷을 보면 newlist 요소로 식별 된 링크 수와 findbyvalue의 링크 수가 동일합니다. 299 페이지에있는 링크.
결과는 다음과 같습니다.
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
#두) 여기서는 findallvalue라는 이름의 웹 요소 목록과 관련된 @FindAll 주석의 작업에 대해 자세히 설명합니다.
@FindAll 주석 내의 각 @FindBy 기준을 예리하게 살펴보면 첫 번째 @FindBy 기준은 className = 'sel'인 요소를 검색하고 두 번째 @FindBy 기준은 XPath = '// a (@ id ='인 특정 요소를 검색합니다. 'tab5')
이제 F12 키를 눌러 nseindia.com 페이지의 요소를 검사하고 @FindBy 기준에 해당하는 요소에 대한 명확한 정보를 얻습니다.
페이지에는 className =”sel”에 해당하는 두 개의 요소가 있습니다.
에) 'Fundamentals'요소에는 목록 태그가 있습니다.
className =”sel”을 사용합니다. 아래 스냅 샷 참조

비) 또 다른 요소 인 'Order Book'에는 클래스 이름이 'sel'인 앵커 태그가있는 XPath가 있습니다.

씨) 두 번째 @FindBy with XPath에는 앵커 태그가 있습니다. 신분증 ' tab5 ”. 검색에 대한 응답으로 식별 된 기본 요소는 단 하나입니다.
아래 스냅 샷을 참조하십시오.

nseindia.com 테스트가 실행되었을 때 검색된 요소 수를 얻었습니다.
@FindAll as 3. 표시 될 때 findallvalue의 요소는 다음과 같습니다. Fundamentals as the 0일인덱스 요소, Order Book을 1로성인덱스 요소와 Fundamentals를 다시 2로nd인덱스 요소. 이미 @FindAll이 각 @FindBy 기준에 대한 요소를 개별적으로 식별한다는 것을 배웠습니다.
동일한 프로토콜에 따라 첫 번째 기준 검색 즉, className =”sel”에 대해 조건을 충족하는 두 요소를 식별하고 'Fundamentals'및 'Order Book'을 가져 왔습니다.
그런 다음 다음 @FindBy 기준으로 이동하고 두 번째 @FindBy에 대해 제공된 xpath에 따라 'Fundamentals'요소를 가져올 수 있습니다. 이것이 마침내 각각 3 개의 요소를 식별 한 이유입니다.
따라서 @FindBy 조건 중 하나를 충족하는 요소를 얻지 못하지만 각 @FindBy를 개별적으로 처리하고 마찬가지로 요소를 식별합니다. 또한 현재 예에서 요소가 고유한지 ( 예 : 이 경우 두 개의 @FindBy 조건 결과의 일부로 두 번 표시되는 'Fundamentals'요소)
#삼) 여기서는 findbysvalue라는 이름의 웹 요소 목록과 관련된 @FindBys 주석의 작업에 대해 자세히 설명합니다. 여기에서도 첫 번째 @FindBy 기준은 className =’sel '인 요소를 검색하고 두 번째 @FindBy 기준은 xpath =“// a (@ id =”tab5”) 인 특정 요소를 검색합니다.
이제 첫 번째 @FindBy 조건에 대해 식별 된 요소는 'Fundamentals'및 'Order Book'이고 두 번째 @FindBy 조건의 요소는 'Fundamentals'입니다.
그렇다면 @FindBys 결과는 @FindAll과 어떻게 다를까요? 이전 섹션에서 @FindBys는 AND 조건 연산자와 동일하므로 모든 @FindBy 조건을 충족하는 요소 또는 요소 목록을 찾습니다.
현재 예제에 따르면 'Fundamentals'값은 class = 'sel'및 id = 'tab5'를 갖는 유일한 요소이므로 두 조건을 모두 충족합니다. 이것이 아웃 테스트 케이스의 @FindBys 크기가 1이고 값을 'Fundamentals'로 표시하는 이유입니다.
Pagefactory에서 요소 캐싱
페이지가로드 될 때마다 @FindBy 또는 driver.findElement ()를 통해 호출을 호출하여 페이지의 모든 요소를 다시 조회하고 페이지의 요소를 새로 검색합니다.
대부분의 경우 요소가 동적이거나 런타임 중에 계속 변경되는 경우 특히 AJAX 요소 인 경우 페이지가로드 될 때마다 페이지의 모든 요소에 대한 새로운 검색이 있다는 것이 확실합니다.
웹 페이지에 정적 요소가있는 경우 요소를 캐싱하면 여러 가지 방법으로 도움이 될 수 있습니다. 요소가 캐시되면 페이지를로드 할 때 요소를 다시 찾을 필요가 없습니다. 대신 캐시 된 요소 저장소를 참조 할 수 있습니다. 이것은 많은 시간을 절약하고 더 나은 성능을 향상시킵니다.
Pagefactory는 주석을 사용하여 요소를 캐싱하는이 기능을 제공합니다. 뿡 빵뀨 .
주석은 드라이버에게 요소에 대해 DOM에서 동일한 로케이터 인스턴스를 사용하고 다시 검색하지 않도록 지시하는 반면 pagefactory의 initElements 메소드는 캐시 된 정적 요소를 저장하는 데 크게 기여합니다. initElements는 요소의 캐싱 작업을 수행합니다.
이것은 pagefactory 개념을 일반 페이지 객체 디자인 패턴보다 특별하게 만듭니다. 그것은 우리가 조금 후에 논의 할 장단점이 있습니다. 예를 들어, Facebook 홈 페이지의 로그인 버튼은 캐시 될 수 있고 캐시하기에 이상적인 요소 인 정적 요소입니다.
이제 @CacheLookUp 주석을 구현하는 방법을 살펴 보겠습니다.
먼저 아래와 같이 Cachelookup 용 패키지를 가져와야합니다.
import org.openqa.selenium.support.CacheLookup
다음은 @CacheLookUp을 사용하여 요소의 정의를 표시하는 스 니펫입니다. UniqueElement가 처음으로 검색되는 즉시 initElement ()는 요소의 캐시 된 버전을 저장하므로 다음에 드라이버가 요소를 찾지 않고 대신 동일한 캐시를 참조하고 요소 오른쪽에 대한 작업을 수행합니다. 떨어져.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
이제 캐시 된 웹 요소에 대한 작업이 캐시되지 않은 웹 요소에 대한 작업보다 더 빠른 실제 프로그램을 살펴 보겠습니다.
nseindia.com 프로그램을 더욱 향상시키기 위해 검색 상자에 대해 캐시 된 요소와 동일한 검색 상자에 대해 캐시되지 않은 요소를 만드는 또 다른 새로운 메서드 인 monitorPerformance ()를 작성했습니다.
그런 다음 캐시 된 요소와 캐시되지 않은 요소 모두에 대해 요소의 태그 이름을 3000 번 얻고 캐시 된 요소와 캐시되지 않은 요소 모두에서 작업을 완료하는 데 걸리는 시간을 측정하려고합니다.
두 사람의 타이밍에서 눈에 띄는 차이를 볼 수 있도록 3000 번을 고려했습니다. 캐시되지 않은 요소와 비교할 때 캐시 된 요소가 태그 이름을 3000 번 더 빨리 가져 오기를 완료해야합니다.
이제 캐시 된 요소가 더 빨리 작동해야하는 이유를 알 수 있습니다. 즉, 드라이버가 첫 번째 조회 후 요소를 조회하지 않고 직접 작업을 계속하도록 지시 받았으며 이는 요소 조회가 수행되는 캐시되지 않은 요소의 경우가 아닙니다. 3000 번 모두 그 다음 작업이 수행됩니다.
다음은 monitorPerformance () 메서드의 코드입니다.
private void monitorPerformance() { //non cached element long NoCache_StartTime = System.currentTimeMillis(); for(int i = 0; i <3000; i ++) { Searchbox.getTagName(); } long NoCache_EndTime = System.currentTimeMillis(); long NoCache_TotalTime=(NoCache_EndTime-NoCache_StartTime)/1000; System.out.println('Response time without caching Searchbox ' + NoCache_TotalTime+ ' seconds'); //cached element long Cached_StartTime = System.currentTimeMillis(); for(int i = 0; i < 3000; i ++) { cachedSearchbox.getTagName(); } long Cached_EndTime = System.currentTimeMillis(); long Cached_TotalTime=(Cached_EndTime - Cached_StartTime)/1000; System.out.println('Response time by caching Searchbox ' + Cached_TotalTime+ ' seconds'); }
실행시 콘솔 창에 아래 결과가 표시됩니다.
결과에 따라 캐시되지 않은 요소에 대한 작업이 완료됩니다. 82 캐시 된 요소에서 작업을 완료하는 데 걸린 시간은 37 초. 이것은 실제로 캐시 된 요소와 캐시되지 않은 요소의 응답 시간에서 눈에 띄는 차이입니다.

Q # 7) Pagefactory 개념에서 @CacheLookUp 주석의 장단점은 무엇입니까?
대답:
@CacheLookUp의 장점과 사용 가능한 상황 :
@CacheLookUp은 요소가 정적이거나 페이지가로드되는 동안 전혀 변경되지 않을 때 가능합니다. 이러한 요소는 런타임을 변경하지 않습니다. 이러한 경우 주석을 사용하여 테스트 실행의 전체 속도를 개선하는 것이 좋습니다.
@CacheLookUp 주석의 단점 :
주석과 함께 요소를 캐시 할 때의 가장 큰 단점은 StaleElementReferenceExceptions가 자주 발생하는 것에 대한 두려움입니다.
동적 요소는 시간 간격의 몇 초 또는 몇 분 동안 빠르게 변경되기 쉬운 요소로 자주 새로 고쳐집니다.
다음은 이러한 동적 요소의 몇 가지 인스턴스입니다.
- 매초마다 타이머를 업데이트하는 스톱워치를 웹 페이지에 표시합니다.
- 날씨 정보를 지속적으로 업데이트하는 프레임입니다.
- 실시간 Sensex 업데이트를보고하는 페이지입니다.
@CacheLookUp 어노테이션 사용에 이상적이거나 실행 가능하지 않습니다. 그렇게하면 StaleElementReferenceExceptions의 예외가 발생할 위험이 있습니다.
이러한 요소를 캐싱 할 때 테스트 실행 중에 요소의 DOM이 변경되지만 드라이버는 캐싱 중에 이미 저장된 DOM 버전을 찾습니다. 이렇게하면 웹 페이지에 더 이상 존재하지 않는 드라이버가 오래된 요소를 조회 할 수 있습니다. 이것이 StaleElementReferenceException이 발생하는 이유입니다.
공장 등급 :
Pagefactory는 여러 팩토리 클래스 및 인터페이스에 구축 된 개념입니다. 이 섹션에서는 몇 가지 팩토리 클래스와 인터페이스에 대해 알아 봅니다. 우리가 살펴볼 몇 가지는 AjaxElementLocatorFactory , ElementLocatorFactory 과 DefaultElementFactory.
Pagefactory가 특정 조건이 충족 될 때까지 요소에 대해 암시 적 또는 명시 적 대기를 통합하는 방법을 제공하는지 궁금한 적이 있습니까? 예: 요소가 표시되고, 활성화되고, 클릭 가능할 때까지)? 그렇다면 여기에 적절한 대답이 있습니다.
AjaxElementLocatorFactory 모든 공장 클래스에서 중요한 기여자 중 하나입니다. AjaxElementLocatorFactory의 장점은 웹 요소의 시간 초과 값을 Object 페이지 클래스에 할당 할 수 있다는 것입니다.
Pagefactory는 명시 적 대기 기능을 제공하지 않지만 클래스를 사용하는 암시 적 대기에 대한 변형이 있습니다. AjaxElementLocatorFactory . 이 클래스는 응용 프로그램이 Ajax 구성 요소 및 요소를 사용할 때 통합하여 사용할 수 있습니다.
다음은 코드에서 구현하는 방법입니다. 생성자 내에서 initElements () 메서드를 사용할 때 AjaxElementLocatorFactory를 사용하여 요소에 대한 암시 적 대기를 제공 할 수 있습니다.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
위의 두 번째 코드 줄은 드라이버가 각로드시 페이지의 모든 요소에 대해 20 초의 시간 제한을 설정해야 함을 의미하며, 20 초 동안 기다린 후에도 요소가 발견되지 않으면 'NoSuchElementException'이 발생합니다. 누락 된 요소에 대해.
다음과 같이 대기를 정의 할 수도 있습니다.
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
위의 코드는 AjaxElementLocatorFactory 클래스가 ElementLocatorFactory 인터페이스를 구현하기 때문에 완벽하게 작동합니다.
여기서 부모 인터페이스 (ElementLocatorFactory)는 자식 클래스 (AjaxElementLocatorFactory)의 객체를 의미합니다. 따라서 AjaxElementLocatorFactory를 사용하여 타임 아웃을 할당하는 동안 '업 캐스팅'또는 '런타임 다형성'이라는 Java 개념이 사용됩니다.
기술적으로 작동하는 방식과 관련하여 AjaxElementLocatorFactory는 먼저 load ()가 반환 될 때로드가 완료되지 않았을 수있는 SlowLoadableComponent를 사용하여 AjaxElementLocator를 만듭니다. load ()를 호출 한 후 isLoaded () 메서드는 구성 요소가 완전히로드 될 때까지 계속 실패해야합니다.
즉, AjaxElementLocator 클래스에서 locator.findElement ()에 대한 호출을 호출하여 SlowLoadableComponent 클래스를 통해로드 될 때까지 시간 초과를 적용하여 코드에서 요소에 액세스 할 때마다 모든 요소가 새로 조회됩니다.
또한 AjaxElementLocatorFactory를 통해 시간 초과를 할당 한 후에는 주석이 무시되므로 @CacheLookUp 주석이있는 요소가 더 이상 캐시되지 않습니다.
방법에도 변형이 있습니다. 당신은 할 수 있습니다 를 불러 initElements () 방법 및 방법 하지 말아야 를 불러 AjaxElementLocatorFactory 요소에 대한 시간 제한을 할당합니다.
# 1) initElements () 메서드에서 아래와 같이 드라이버 객체 대신 요소 이름을 지정할 수도 있습니다.
PageFactory.initElements( , this);
위 변형의 initElements () 메서드는 DefaultElementFactory 클래스에 대한 호출을 내부적으로 호출하고 DefaultElementFactory의 생성자는 SearchContext 인터페이스 객체를 입력 매개 변수로받습니다. 웹 드라이버 개체와 웹 요소는 모두 SearchContext 인터페이스에 속합니다.
이 경우 initElements () 메서드는 앞서 언급 된 요소로만 초기화되며 웹 페이지의 모든 요소가 초기화되지는 않습니다.
#두) 그러나 여기에 특정 방식으로 AjaxElementLocatorFactory 객체를 호출해서는 안되는 방법을 나타내는이 사실에 대한 흥미로운 변형이 있습니다. AjaxElementLocatorFactory와 함께 위의 initElements () 변형을 사용하면 실패합니다.
예: 아래 코드 즉, AjaxElementLocatorFactory 정의에 드라이버 객체 대신 요소 이름을 전달하면 AjaxElementLocatorFactory 클래스의 생성자가 작동하지 않으므로 웹 드라이버 객체 만 입력 매개 변수로 사용하므로 웹 요소가있는 SearchContext 객체가 작동하지 않습니다.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
Q # 8) 페이지 팩토리를 사용하는 것이 일반 페이지 개체 디자인 패턴보다 가능한 옵션입니까?
대답: 이것은 사람들이 가지고있는 가장 중요한 질문이며 이것이 튜토리얼의 끝에서 그것을 다루려고 생각한 이유입니다. 이제 Pagefactory의 개념, 사용 된 주석, 지원되는 추가 기능, 코드를 통한 구현, 장단점에서 시작하여 Pagefactory에 대한 '내부 및 외부'를 알고 있습니다.
그러나 우리는 pagefactory에 좋은 것들이 너무 많다면 왜 그 사용법을 고수해서는 안된다는이 본질적인 질문에 남아 있습니다.
Pagefactory에는 CacheLookUp이라는 개념이 포함되어 있습니다.이 개념은 자주 업데이트되는 요소의 값과 같은 동적 요소에는 적합하지 않습니다. 따라서 CacheLookUp이없는 pagefactory는 옵션을 선택하는 것이 좋을까요? 예, xpath가 정적 인 경우입니다.
그러나 단점은 페이지 팩토리가없는 페이지 객체 디자인이 궁극적으로 잘 작동하지만 페이지 팩토리 개념이 동적 xpath와 똑같이 잘 작동한다는 것을 알고있는 현대 시대 애플리케이션이 무거운 동적 요소로 가득 차 있다는 것입니다. 아마. 다음은 간단한 예입니다.
nseindia.com 웹 페이지에서 아래와 같은 표를 볼 수 있습니다.

테이블의 xpath는
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
첫 번째 열 'Buy Qty'의 각 행에서 값을 검색하려고합니다. 이렇게하려면 행 카운터를 증가시켜야하지만 열 인덱스는 1로 유지됩니다. 주석이 정적 값을 허용하고 변수를 전달할 수 없기 때문에 @FindBy 주석에이 동적 XPath를 전달할 수있는 방법이 없습니다. 그것.
일반적인 POM이 잘 작동하는 동안 pagefactory가 완전히 실패하는 곳은 다음과 같습니다. for 루프를 사용하여 driver.findElement () 메서드에서 이러한 동적 xpath를 사용하여 행 인덱스를 쉽게 증가시킬 수 있습니다.
결론
페이지 개체 모델은 Selenium 자동화 프레임 워크에서 사용되는 디자인 개념 또는 패턴입니다.
메서드의 이름 지정 대류는 페이지 개체 모델에서 사용자 친화적입니다. POM의 코드는 이해하기 쉽고 재사용 및 유지 관리가 가능합니다. POM에서 웹 요소에 변경 사항이 있으면 모든 클래스를 편집하는 것이 아니라 해당 클래스를 변경하는 것으로 충분합니다.
일반적인 POM과 마찬가지로 Pagefactory는 적용하기에 훌륭한 개념입니다. 그러나 일반적인 POM이 가능한 곳과 Pagefactory가 적합한 곳을 알아야합니다. 정적 응용 프로그램 (XPath와 요소가 모두 정적 임)에서 Pagefactory는 더 나은 성능의 이점을 추가하여 자유롭게 구현할 수 있습니다.
또는 응용 프로그램이 동적 및 정적 요소를 모두 포함하는 경우 각 웹 요소의 실행 가능성에 따라 Pagefactory와 Pagefactory없이 pom을 혼합하여 구현할 수 있습니다.
작성자 :이 튜토리얼은 Shobha D가 작성했습니다. 그녀는 프로젝트 리더로 일하고 있으며 수동, 자동화 (Selenium, IBM Rational Functional Tester, Java) 및 API 테스팅 (SOAPUI 및 Rest assured in Java) 분야에서 9 년 이상의 경험을 가지고 있습니다. .
이제 Pagefactory의 추가 구현에 대해 설명하겠습니다.
행복한 탐험 !!!
추천 도서
- 30 개 이상의 최고의 셀레늄 튜토리얼 : 실제 예제로 셀레늄 배우기
- 효율적인 Selenium 스크립팅 및 문제 해결 시나리오 – Selenium 자습서 # 27
- 로그로 Selenium 스크립트 디버깅 (Log4j 튜토리얼) – Selenium 튜토리얼 # 26
- JUnit 프레임 워크 소개 및 Selenium 스크립트에서의 사용법 – Selenium Tutorial # 11
- Selenium 자동화 프로젝트의 테스트 추정에 영향을 미치는 7 가지 요인 – Selenium Tutorial # 32
- Junit 및 TestNG 프레임 워크를 사용하는 Selenium의 어설 션
- Selenium 스크립트 생성을 위해 TestNG 프레임 워크를 사용하는 방법-TestNG Selenium Tutorial # 12
- Selenium에서 TestNG 주석을 사용하는 방법 알아보기 (예제 포함)