page object model with page factory selenium tutorial
この詳細なチュートリアルでは、Pagefactoryを使用したページオブジェクトモデル(POM)のすべてを例を使用して説明します。 SeleniumでのPOMの実装についても学ぶことができます。
このチュートリアルでは、ページファクトリアプローチを使用してページオブジェクトモデルを作成する方法を理解します。 私たちは焦点を当てます:
- ファクトリクラス
- ページファクトリパターンを使用して基本的なPOMを作成する方法
- ページファクトリアプローチで使用されるさまざまな注釈
Pagefactoryとは何か、そしてそれをPageオブジェクトモデルと一緒に使用する方法を理解する前に、一般にPOMとして知られているPage ObjectModelとは何かを理解しましょう。
=> すべての人のためのSeleniumトレーニングシリーズを見るには、ここにアクセスしてください。
学習内容:
ページオブジェクトモデル(POM)とは何ですか?
理論的な用語は、 ページオブジェクトモデル テスト対象のアプリケーションで使用可能なWeb要素のオブジェクトリポジトリを構築するために使用されるデザインパターンとして。テスト対象の特定のアプリケーションのSelenium自動化のフレームワークとしてこれを参照する人はほとんどいません。
ただし、ページオブジェクトモデルという用語について私が理解したことは次のとおりです。
#1) これは、アプリケーションの各画面またはページに対応する個別のJavaクラスファイルがあるデザインパターンです。クラスファイルには、UI要素のオブジェクトリポジトリとメソッドを含めることができます。
#二) ページに巨大なWeb要素がある場合、ページのオブジェクトリポジトリクラスは、対応するページのメソッドを含むクラスから分離できます。
例: (アカウントの登録)ページに多くの入力フィールドがある場合は、アカウントの登録ページのUI要素のオブジェクトリポジトリを形成するクラスRegisterAccountObjects.javaが存在する可能性があります。
ページ上でさまざまなアクションを実行するすべてのメソッドを含む、RegisterAccountObjectsを拡張または継承する別個のクラスファイルRegisterAccount.javaを作成できます。
#3) さらに、パッケージの下に{ropertiesファイル、Excelテストデータ、およびCommonメソッドを含む汎用パッケージが存在する可能性があります。
例: アプリケーションのすべてのページで非常に簡単に使用できるDriverFactory
例を挙げてPOMを理解する
小切手 ここに POMの詳細については。
以下は、Webページのスナップショットです。
これらの各リンクをクリックすると、ユーザーは新しいページにリダイレクトされます。
これは、Webサイトの各ページに対応するPageオブジェクトモデルを使用して、Seleniumを使用してプロジェクト構造を構築する方法のスナップショットです。すべてのJavaクラスには、ページ内でさまざまなアクションを実行するためのオブジェクトリポジトリとメソッドが含まれています。
さらに、これらのページのクラスファイルへの呼び出しを呼び出す別のJUNITまたはTestNGまたはJavaクラスファイルがあります。
なぜページオブジェクトモデルを使用するのですか?
POMまたはページオブジェクトモデルと呼ばれるこの強力なSeleniumフレームワークの使用法については話題があります。ここで、「なぜPOMを使用するのか」という疑問が生じます。
これに対する簡単な答えは、POMはデータ駆動型のモジュラーフレームワークとハイブリッドフレームワークの組み合わせであるということです。これは、QAがコードを面倒なことなく維持しやすくし、コードの冗長性や重複を防ぐのに役立つように、スクリプトを体系的に整理するためのアプローチです。
たとえば、特定のページでロケーター値に変更があった場合、他のコードに影響を与えることなく、それぞれのページのスクリプトでのみその迅速な変更を識別して行うのは非常に簡単です。
次の理由により、SeleniumWebdriverでページオブジェクトモデルの概念を使用します。
- このPOMモデルにオブジェクトリポジトリが作成されます。テストケースに依存せず、別のプロジェクトで再利用できます。
- メソッドの命名規則は非常に簡単で、理解しやすく、より現実的です。
- Pageオブジェクトモデルの下で、別のプロジェクトで再利用できるページクラスを作成します。
- Pageオブジェクトモデルは、いくつかの利点があるため、開発されたフレームワークにとって簡単です。
- このモデルでは、ログインページ、ホームページ、従業員の詳細ページ、パスワードの変更ページなど、Webアプリケーションのさまざまなページに対して個別のクラスが作成されます。
- ウェブサイトのいずれかの要素に変更があった場合、すべてのクラスではなく、1つのクラスで変更を加えるだけで済みます。
- 設計されたスクリプトは、ページオブジェクトモデルアプローチでより再利用可能で、読みやすく、保守しやすくなっています。
- そのプロジェクト構造は非常に簡単で理解しやすいものです。
- Web要素を初期化し、要素をキャッシュに格納するために、ページオブジェクトモデルでPageFactoryを使用できます。
- TestNGは、ページオブジェクトモデルアプローチに統合することもできます。
Seleniumでの単純なPOMの実装
#1)自動化するシナリオ
次に、ページオブジェクトモデルを使用して、特定のシナリオを自動化します。
シナリオを以下に説明します。
ステップ1: サイト「https://demo.vtiger.com」を起動します。
ステップ2: 有効な資格情報を入力してください。
ステップ3: サイトにログインします。
ステップ4: ホームページを確認します。
ステップ5: サイトからログアウトします。
ステップ6: ブラウザを閉じます。
#2)POMの上記のシナリオのSeleniumスクリプト
次に、以下で説明するように、EclipseでPOM構造を作成します。
ステップ1: Eclipseでプロジェクトを作成する– POMベースの構造:
a)プロジェクト「ページオブジェクトモデル」を作成します。
b)プロジェクトの下に3つのパッケージを作成します。
- 図書館
- ページ
- テストケース
図書館: この下で、ブラウザの起動、スクリーンショットなどのテストケースに、何度も呼び出す必要のあるコードを配置します。ユーザーは、プロジェクトのニーズに基づいて、その下にクラスを追加できます。
ページ: この下で、クラスはWebアプリケーションのページごとに作成され、アプリケーションのページ数に基づいてさらにページクラスを追加できます。
テストケース: この下で、ログインテストケースを作成し、必要に応じてアプリケーション全体をテストするためにテストケースを追加できます。
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ブラウザを起動します。
- デモWebサイトがブラウザで開きます。
- デモサイトにログインします。
- ホームページを確認します。
- サイトからログアウトします。
- ブラウザを閉じます。
それでは、注目を集めるこのチュートリアルの主要な概念を探りましょう。 「ページファクトリー」。
Pagefactoryとは何ですか?
PageFactoryは、「ページオブジェクトモデル」を実装する方法です。ここでは、ページオブジェクトリポジトリとテストメソッドの分離の原則に従います。これは、非常に最適化されたページオブジェクトモデルの組み込みの概念です。
ここで、Pagefactoryという用語をより明確にしましょう。
#1) まず、Pagefactoryと呼ばれる概念は、ページ上のWeb要素のオブジェクトリポジトリを作成するための構文とセマンティクスの観点から別の方法を提供します。
#二) 次に、Web要素の初期化にわずかに異なる戦略を使用します。
#3) UI Web要素のオブジェクトリポジトリは、次を使用して構築できます。
- 通常の「PagefactoryのないPOM」と、
- または、「POMwithPagefactory」を使用することもできます。
以下に、同じものを図で表したものを示します。
次に、通常のPOMとPagefactoryを使用したPOMを区別するすべての側面を見ていきます。
a)通常のPOMを使用した要素の検索とPagefactoryを使用したPOMの構文の違い。
例えば 、クリック ここに ページに表示される検索フィールドを検索します。
PagefactoryのないPOM:
#1)以下は、通常のPOMを使用して検索フィールドを見つける方法です。
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
#2)以下のステップでは、値「investment」を「SearchNSE」フィールドに渡します。
searchNSETxt.sendkeys(“investment”);
Pagefactoryを使用したPOM:
#1) 以下に示すように、Pagefactoryを使用して検索フィールドを見つけることができます。
注釈 @FindBy Pagefactoryでは要素を識別するために使用されますが、PagefactoryのないPOMは driver.findElement() 要素を見つける方法。
後のPagefactoryの2番目のステートメント @FindBy タイプのを割り当てています WebElement メソッドの戻り値の型としてWebElementクラス型の要素名を割り当てるのとまったく同じように機能するクラス driver.findElement() これは通常のPOM(この例ではsearchNSETxt)で使用されます。
私たちは見ていきます @FindBy このチュートリアルの次の部分で詳細に注釈を付けます。
@FindBy(id = 'searchBox') WebElement searchNSETxt;
#二) 以下のステップでは、値「investment」をSearch NSEフィールドに渡し、構文は通常のPOM(PagefactoryのないPOM)と同じままです。
searchNSETxt.sendkeys(“investment”);
b)通常のPOMを使用したWeb要素の初期化戦略とPagefactoryを使用したPOMの戦略の違い。
PagefactoryなしでPOMを使用する:
以下に、Chromeドライバーパスを設定するためのコードスニペットを示します。ドライバーという名前でWebDriverインスタンスが作成され、ChromeDriverが「ドライバー」に割り当てられます。次に、同じドライバーオブジェクトを使用して、National Stock Exchange Webサイトを起動し、searchBoxを見つけて、フィールドに文字列値を入力します。
ここで強調したいのは、ページファクトリのないPOMの場合、ドライバインスタンスが最初に作成され、driver.findElement()またはdriverを使用してそのWeb要素が呼び出されるたびに、すべてのWeb要素が新たに初期化されることです。 .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では、Web要素を明示的に初期化する必要がありますが、Pagefactoryアプローチでは、各Web要素を明示的に初期化せずにすべての要素をinitElements()で初期化します。
例えば: WebElementが宣言されているが、通常のPOMで初期化されていない場合、「変数の初期化」エラーまたはNullPointerExceptionがスローされます。したがって、通常のPOMでは、各WebElementを明示的に初期化する必要があります。この場合、PageFactoryには通常のPOMよりも優れた利点があります。
Web要素を初期化しないようにしましょう BDate (PagefactoryなしのPOM)、エラー「Initialize variable」が表示され、ユーザーにnullに初期化するように求めることがわかります。したがって、要素を見つけるときに要素が暗黙的に初期化されるとは限りません。
明示的に初期化された要素BDate(PagefactoryなしのPOM):
それでは、PageFactoryを使用して完全なプログラムのいくつかのインスタンスを見て、実装の側面を理解する際のあいまいさを排除しましょう。
例1:
- 「http://www.nseindia.com/」にアクセスします
- 検索フィールドの横にあるドロップダウンから、(通貨デリバティブ)を選択します。
- 「USDINR」を検索します。結果のページで「米ドル-インドルピー-USDINR」というテキストを確認します。
プログラムの構造:
- すべてのWeb要素を初期化するためのコンストラクターであるnseindia.comのページファクトリコンセプトを使用するオブジェクトリポジトリを含むPagefactoryClass.javaが作成され、メソッドselectCurrentDerivative()で検索ボックスドロップダウンフィールドから値を選択し、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」にアクセスします
- オートカレーのリンクに移動します。
- HauteCurryページに「StartNewSomething」というテキストが含まれているかどうかを確認します。
プログラムの構造
- すべてのWeb要素を初期化するためのコンストラクターであるshoppersstop.comのpagefactoryコンセプトを使用するオブジェクトリポジトリを含むshopperstopPagefactory.javaが作成され、開くアラートポップアップボックスを処理するメソッドcloseExtraPopup()、HauteCurryをクリックするためのclickOnHauteCurryLink()リンクしてverifyStartNewSomething()を実行して、HauteCurryページに「Startnewsomething」というテキストが含まれているかどうかを確認します。
- 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
パートI
パートII
Factoryクラスは、ページオブジェクトの使用をより簡単かつ簡単にするために使用されます。
- まず、アノテーションでWeb要素を見つける必要があります @FindBy ページクラスで 。
- 次に、ページクラスをインスタンス化するときにinitElements()を使用して要素を初期化します。
#1) @FindBy:
@FindByアノテーションは、さまざまなロケーターを使用してWeb要素を検索および宣言するためにPageFactoryで使用されます。ここでは、Web要素を見つけるために使用される属性とその値を@FindByアノテーションに渡し、WebElementが宣言されます。
注釈を使用する方法は2つあります。
例えば:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
ただし、前者はWebElementsを宣言する標準的な方法です。
'どうやって' はクラスであり、ID、XPATH、CLASSNAME、LINKTEXTなどの静的変数があります。
「使用する」 –静的変数に値を割り当てる。
上記で 例 、「id」属性を使用してWeb要素「Email」を検索しました。同様に、@ FindByアノテーションで次のロケーターを使用できます。
- クラス名
- css
- 名前
- xpath
- タグ名
- linkText
- partialLinkText
#2)initElements():
initElementsは、PageFactoryクラスの静的メソッドであり、@ FindByアノテーションによって配置されたすべてのWeb要素を初期化するために使用されます。したがって、Pageクラスを簡単にインスタンス化できます。
initElements(WebDriver driver, java.lang.Class pageObjectClass)
また、POMはOOPSの原則に従っていることも理解する必要があります。
- WebElementsは、プライベートメンバー変数(データ非表示)として宣言されます。
- WebElementsを対応するメソッド(カプセル化)にバインドします。
ページファクトリパターンを使用してPOMを作成する手順
#1) Webページごとに個別のJavaクラスファイルを作成します。
#二) 各クラスで、すべてのWebElementを変数として宣言し(アノテーション– @FindByを使用)、initElement()メソッドを使用して初期化する必要があります。宣言されたWebElementは、アクションメソッドで使用するために初期化する必要があります。
#3) それらの変数に作用する対応するメソッドを定義します。
簡単なシナリオの例を見てみましょう。
- アプリケーションのURLを開きます。
- メールアドレスとパスワードのデータを入力します。
- ログインボタンをクリックします。
- 検索ページでログインメッセージが成功したことを確認します。
ページレイヤー
ここに2ページあります。
- ホームページ – URLが入力されたときに開き、ログイン用のデータを入力するページ。
- SearchPage –ログインに成功した後に表示されるページ。
ページレイヤーでは、Webアプリケーションの各ページが個別のJavaクラスとして宣言され、そのロケーターとアクションがそこに記載されています。
リアルタイムの例でPOMを作成する手順
#1)ページごとにJavaクラスを作成します。
これで 例 、「ホーム」ページと「検索」ページの2つのWebページにアクセスします。
したがって、Page Layer(またはcom.automation.pagesなどのパッケージ)に2つのJavaクラスを作成します。
Package Name :com.automation.pages HomePage.java SearchPage.java
#2)アノテーション@FindByを使用してWebElementsを変数として定義します。
私たちは以下と対話します:
- ホームページの電子メール、パスワード、ログインボタンフィールド。
- 検索ページに成功したメッセージ。
したがって、@ FindByを使用してWebElementsを定義します
例えば: 属性IDを使用してEmailAddressを識別する場合、その変数宣言は次のようになります。
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
#3)WebElementsで実行されるアクションのメソッドを作成します。
以下のアクションがWebElementsで実行されます。
- (メールアドレス)フィールドにアクションを入力します。
- 「パスワード」フィールドにアクションを入力します。
- ログインボタンのアクションをクリックします。
例えば、 ユーザー定義メソッドは、WebElementのアクションごとに次のように作成されます。
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
ここでは、メインのテストケースからユーザーが入力を送信するため、Idはメソッドのパラメーターとして渡されます。
注意 :テストレイヤーのメインクラスからドライバーインスタンスを取得し、PageFactory.InitElement()を使用してページクラスで宣言されたWebElements(ページオブジェクト)を初期化するには、ページレイヤーの各クラスにコンストラクターを作成する必要があります。 。
ここではドライバーを開始しませんが、ページレイヤークラスのオブジェクトが作成されるときに、そのインスタンスがメインクラスから受信されます。
InitElement() –メインクラスのドライバーインスタンスを使用して、宣言されたWebElementsを初期化するために使用されます。つまり、WebElementsはドライバーインスタンスを使用して作成されます。 WebElementsが初期化された後でのみ、アクションを実行するためのメソッドで使用できます。
以下に示すように、ページごとに2つの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クラスのオブジェクトを(Webページごとに)作成し、ドライバーインスタンスをパラメーターとして渡します。
- 作成されたオブジェクトを使用して、アクション/検証を実行するために、(各Webページの)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を見つけるために使用されます 1つの基準で 。
#2)@FindBys
WebElementを見つけるために使用されます 複数の基準 与えられたすべての基準に一致する必要があります。これらの基準は、親子関係で言及する必要があります。つまり、これはAND条件付き関係を使用して、指定された基準を使用してWebElementsを検索します。複数の@FindByを使用して、各基準を定義します。
例えば:
WebElementのHTMLソースコード:
POMの場合:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
上記の例では、WebElementの「SearchButton」は次の場合にのみ配置されます 両方に一致 id値が「searchId_1」で名前値が「search_field」の基準。最初の基準は親タグに属し、2番目の基準は子タグに属することに注意してください。
#3)@FindAll
WebElementを見つけるために使用されます 複数の基準 そしてそれは与えられた基準の少なくとも1つに一致する必要があります。これは、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の「ユーザー名」が 少なくとも1つに一致する 言及された基準の。
#4)@CacheLookUp
WebElementがテストケースでより頻繁に使用される場合、Seleniumはテストスクリプトが実行されるたびにWebElementを検索します。これらの場合、特定のWebElementがすべての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()を使用してWeb要素を初期化するPagefactoryの戦略を理解したので、メソッドのさまざまなバージョンを理解してみましょう。
私たちが知っているメソッドは、入力パラメーターとしてドライバーオブジェクトと現在のクラスオブジェクトを受け取り、ページ上のすべての要素を暗黙的かつプロアクティブに初期化することによってページオブジェクトを返します。
実際には、上記のセクションに示されているコンストラクターの使用は、他の使用方法よりも望ましい方法です。
メソッドを呼び出す別の方法は次のとおりです。
#1) 「this」ポインタを使用する代わりに、現在のクラスオブジェクトを作成し、それにドライバインスタンスを渡して、パラメータを使用して静的メソッドinitElementsを呼び出すことができます。つまり、作成されたばかりのドライバオブジェクトとクラスオブジェクトです。
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
#二) Pagefactoryクラスを使用して要素を初期化する3番目の方法は、「リフレクション」と呼ばれる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つのロケーター戦略を使用します。
- id
- 名前
- クラス名
- xpath
- css
- タグ名
- linkText
- partialLinkText
Q#2)@FindByアノテーションの使用法にも異なるバージョンがありますか?
回答: 検索するWeb要素がある場合は、アノテーション@FindByを使用します。 @FindByを使用する別の方法と、さまざまなロケーター戦略についても詳しく説明します。
@FindByのバージョン1の使用方法はすでに見てきました。
@FindBy(id = 'cidkeyword') WebElement Symbol;
@FindByのバージョン2は、入力パラメーターを次のように渡すことによるものです。 どうやって そして 使用する 。
どうやって webelementを識別するために使用するロケーター戦略を探します。キーワード を使用して ロケーター値を定義します。
理解を深めるために以下を参照してください。
- How.IDは、を使用して要素を検索します id 戦略とそれが識別しようとする要素はid =を持っています cidkeyword。
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- How.CLASS_NAMEは、を使用して要素を検索します クラス名 戦略とそれが識別しようとする要素にはclass =があります newclass。
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
Q#3)@FindByの2つのバージョンに違いはありますか?
回答: 答えは「いいえ」です。2つのバージョンに違いはありません。最初のバージョンは、2番目のバージョンと比較して短くて簡単です。
Q#4)配置するWeb要素のリストがある場合、ページファクトリで何を使用しますか?
回答: 通常のページオブジェクトデザインパターンでは、同じクラスまたはタグ名に属する複数の要素を見つけるための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を使用しないPageオブジェクトデザインとPagefactoryを使用するPageオブジェクトデザインの両方を同じプログラムで使用できますか?
回答: はい、Pagefactoryを使用しないページオブジェクトデザインとPagefactoryを使用するページオブジェクトデザインの両方を同じプログラムで使用できます。あなたは以下のプログラムを通過することができます 質問#6の回答 プログラムで両方がどのように使用されているかを確認します。
覚えておくべきことの1つは、キャッシュ機能を備えたPagefactoryの概念は動的要素では避ける必要があるのに対し、ページオブジェクトの設計は動的要素でうまく機能するということです。ただし、Pagefactoryは静的要素にのみ適しています。
Q#6)複数の基準に基づいて要素を識別する別の方法はありますか?
複数のYouTubeビデオをmp3に変換する
回答: 複数の基準に基づいて要素を識別する別の方法は、アノテーション@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”で2番目の要素を識別します。
FindBy基準ごとに1つの要素が識別されたとすると、@ FindAllはそれぞれ2つの要素をリストします。基準ごとに複数の要素が識別される可能性があることを忘れないでください。したがって、簡単に言えば、@ FindAll と同等の動作 または @FindBy基準の演算子が渡されました。
#2)@FindBys:
FindBysは、ByChainedで説明されているように、ルックアップでチェーン内の一連の@FindByタグを使用する必要があることを示すためにページオブジェクトのフィールドをマークするために使用されます。必要なWebElementオブジェクトが指定されたすべての基準に一致する必要がある場合は、@ FindBysアノテーションを使用します。
@FindBysを使用する構文は次のとおりです。
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
説明: @FindBysは、すべての@FindBy基準に準拠する要素を検索および識別し、それらをリストします。上記の例では、name =” foo”およびclassName =” bar”の要素を検索します。
@FindAllは、指定された基準で名前とclassNameで識別される要素が1つあると想定した場合、1つの要素をリストすることになります。
渡されたすべてのFindBy条件を満たす要素が1つもない場合、@ FindBysの結果はゼロ要素になります。すべての条件が複数の要素を満たしている場合、識別されたWeb要素のリストが存在する可能性があります。簡単に言えば、@ FindBys と同等の動作 そして @FindBy基準の演算子が渡されました。
詳細なプログラムを通じて、上記のすべてのアノテーションの実装を見てみましょう。
前のセクションで示したwww.nseindia.comプログラムを変更して、アノテーション@ FindBy、@ FindBys、および@FindAllの実装を理解します。
#1)PagefactoryClassのオブジェクトリポジトリは次のように更新されます。
リストnewlist = driver.findElements(By.tagName( 'a'));
@FindBy (どのように=どのように。 タグ名 、using =“ 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は、ページファクトリの概念を持つ検索戦略を通じて、ページ上のすべてのリンクの数を取得するために作成されます。
driver.findElement()と@FindByの両方が同じジョブを実行し、同じ要素を識別することが正しいことが証明されています。上記の結果のコンソールウィンドウのスクリーンショットを見ると、要素newlistで識別されたリンクの数とfindbyvalueの数は同じです。 299 ページにあるリンク。
結果は以下のようになりました。
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
#二) ここでは、findallvalueという名前のWeb要素のリストに関連する@FindAllアノテーションの動作について詳しく説明します。
@FindAllアノテーション内の各@FindBy条件を注意深く見て、最初の@FindBy基準はclassName = 'sel'の要素を検索し、2番目の@FindBy基準はXPath =“ // a (@ id =の特定の要素を検索します'tab5')
ここで、F12を押して、ページnseindia.comの要素を調べ、@ FindBy基準に対応する要素の特定の明快さを取得しましょう。
className =” sel”に対応するページには2つの要素があります。
に) 要素「Fundamentals」にはリストタグがあります。
className =” sel”を使用します。 以下のスナップショットを参照してください

b) 別の要素「OrderBook」には、クラス名が「sel」のアンカータグを持つXPathがあります。

c) XPathを使用した2番目の@FindByには、アンカータグがあります。 id は「 tab5 」。検索に応じて特定された要素は、Fundamentalsだけです。
以下のスナップショットを参照してください。

nseindia.comテストが実行されたとき、検索された要素の数を取得しました。
@FindAll as3。表示されたときのfindallvalueの要素は次のとおりです。0としての基本thインデックス要素、1としてのオーダーブックstインデックス要素とファンダメンタルズを2として再びndインデックス要素。 @FindAllは、各@FindBy基準の要素を個別に識別することをすでに学びました。
同じプロトコルに従って、最初の基準検索、つまりclassName =” sel”に対して、条件を満たす2つの要素を識別し、「Fundamentals」と「OrderBook」をフェッチしました。
次に、次の@FindBy基準に移動し、2番目の@FindByに指定されたxpathに従って、要素「Fundamentals」をフェッチできます。これが、最終的にそれぞれ3つの要素を特定した理由です。
したがって、@ FindBy条件を満たす要素は取得されませんが、@ FindByのそれぞれを個別に処理し、同様に要素を識別します。さらに、現在の例では、要素が一意であるかどうかを監視しないことも確認しました( 例えば。 この場合、2つの@FindBy基準の結果の一部として2回表示された要素「Fundamentals」)
#3) ここでは、findbysvalueという名前のWeb要素のリストに関連する@FindBysアノテーションの動作について詳しく説明します。ここでも、最初の@FindBy基準はclassName = ’sel’の要素を検索し、2番目の@FindBy基準はxpath =“ // a (@ id =” tab5”)の特定の要素を検索します。
これで、最初の@FindBy条件で識別される要素は「Fundamentals」と「OrderBook」であり、2番目の@FindBy基準の要素は「Fundamentals」です。
では、@ FindBysの結果は@FindAllとどのように異なるのでしょうか?前のセクションで、@ FindBysはAND条件演算子と同等であるため、すべての@FindBy条件を満たす要素または要素のリストを検索することを学びました。
現在の例によると、値「Fundamentals」は、class =” sel”とid =” tab5”を持つ唯一の要素であり、両方の条件を満たす。これが、テストケースの@FindBysサイズが1であり、値が「Fundamentals」として表示される理由です。
Pagefactoryで要素をキャッシュする
ページが読み込まれるたびに、@ FindByまたはdriver.findElement()を介して呼び出しを呼び出すことにより、ページ上のすべての要素が再度検索され、ページ上の要素が新たに検索されます。
要素が動的であるか、実行時に変更され続ける場合、特にAJAX要素の場合、ほとんどの場合、ページが読み込まれるたびに、ページ上のすべての要素が新たに検索されることは確かに理にかなっています。
Webページに静的要素がある場合、要素をキャッシュするとさまざまな方法で役立ちます。要素がキャッシュされると、ページの読み込み時に要素を再度見つける必要はありません。代わりに、キャッシュされた要素リポジトリを参照できます。これにより、多くの時間が節約され、パフォーマンスが向上します。
Pagefactoryは、注釈を使用して要素をキャッシュするこの機能を提供します @CacheLookUp 。
アノテーションは、DOMからのロケーターの同じインスタンスを要素に使用し、それらを再度検索しないようにドライバーに指示しますが、ページファクトリのinitElementsメソッドはキャッシュされた静的要素の格納に大きく貢献します。 initElementsは、要素のキャッシュジョブを実行します。
これにより、ページファクトリの概念が通常のページオブジェクトデザインパターンよりも特別になります。独自の長所と短所がありますが、これについては後で説明します。たとえば、Facebookホームページのログインボタンは静的な要素であり、キャッシュすることができ、キャッシュするのに理想的な要素です。
アノテーション@CacheLookUpを実装する方法を見てみましょう
最初に、以下のようにCachelookupのパッケージをインポートする必要があります。
import org.openqa.selenium.support.CacheLookup
以下は、@ CacheLookUpを使用して要素の定義を表示するスニペットです。 UniqueElementが最初に検索されるとすぐに、initElement()は要素のキャッシュされたバージョンを保存するため、次回ドライバーが要素を検索せずに、同じキャッシュを参照し、要素の右側でアクションを実行します。離れて。
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
キャッシュされたWeb要素でのアクションがキャッシュされていないWeb要素でのアクションよりもどのように速いかを実際のプログラムで見てみましょう。
nseindia.comプログラムをさらに強化するために、別の新しいメソッドmonitorPerformance()を作成しました。このメソッドでは、検索ボックスのキャッシュ要素と同じ検索ボックスの非キャッシュ要素を作成します。
次に、キャッシュされた要素とキャッシュされていない要素の両方について要素のタグ名を3000回取得し、キャッシュされた要素とキャッシュされていない要素の両方でタスクを完了するのにかかる時間を測定しようとします。
2つのタイミングの目に見える違いを確認できるように、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が頻繁に発生する恐れがあることです。
動的要素は、時間間隔の数秒または数分で急速に変化する可能性のある要素で頻繁に更新されます。
以下は、動的要素のそのようなインスタンスのいくつかです。
- タイマーを毎秒更新し続けるストップウォッチをWebページに配置します。
- 天気予報を常に更新するフレーム。
- ライブのSensexアップデートを報告するページ。
これらは、アノテーション@CacheLookUpの使用にはまったく理想的または実現可能ではありません。そうした場合、StaleElementReferenceExceptionsの例外が発生するリスクがあります。
このような要素をキャッシュすると、テストの実行中に要素のDOMが変更されますが、ドライバーはキャッシュ中に既に保存されているDOMのバージョンを探します。これにより、古い要素がWebページに存在しなくなったドライバーによって検索されるようになります。これが、StaleElementReferenceExceptionがスローされる理由です。
ファクトリクラス:
Pagefactoryは、複数のファクトリクラスとインターフェイスに基づいて構築された概念です。このセクションでは、いくつかのファクトリクラスとインターフェイスについて学習します。そのうちのいくつかを見ていきます AjaxElementLocatorFactory 、 ElementLocatorFactory そして DefaultElementFactory。
Pagefactoryが、特定の条件が満たされるまで要素を待機する暗黙的または明示的な待機を組み込む方法を提供するかどうか疑問に思ったことはありませんか( 例: 要素が表示、有効化、クリック可能になるまで)?はいの場合、これが適切な答えです。
AjaxElementLocatorFactory すべてのファクトリクラスの中で重要な貢献者の1つです。 AjaxElementLocatorFactoryの利点は、Web要素のタイムアウト値をObjectページクラスに割り当てることができることです。
Pagefactoryは明示的な待機機能を提供していませんが、クラスを使用した暗黙的な待機のバリエーションがあります。 AjaxElementLocatorFactory 。このクラスは、アプリケーションがAjaxコンポーネントと要素を使用するときに組み込むことができます。
これがコードに実装する方法です。コンストラクター内で、initElements()メソッドを使用すると、AjaxElementLocatorFactoryを使用して、要素を暗黙的に待機できます。
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
コードの上記の2行目は、ドライバーがページ上のすべての要素に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は最初にSlowLoadableComponentを使用してAjaxElementLocatorを作成しますが、load()が戻ったときにロードが完了していない可能性があります。 load()の呼び出し後、isLoaded()メソッドは、コンポーネントが完全にロードされるまで失敗し続ける必要があります。
つまり、AjaxElementLocatorクラスからlocator.findElement()の呼び出しを呼び出して、コード内で要素にアクセスするたびに、すべての要素が新たに検索され、SlowLoadableComponentクラスを介して読み込まれるまでタイムアウトが適用されます。
さらに、AjaxElementLocatorFactoryを介してタイムアウトを割り当てた後、アノテーションが無視されるため、@ CacheLookUpアノテーションのある要素はキャッシュされなくなります。
方法にもバリエーションがあります あなたはできる を呼び出す initElements ()方法と方法 いけない を呼び出す AjaxElementLocatorFactory 要素にタイムアウトを割り当てます。
#1)以下のinitElements()メソッドで示すように、ドライバーオブジェクトの代わりに要素名を指定することもできます。
PageFactory.initElements( , this);
上記のバリアントのinitElements()メソッドは、DefaultElementFactoryクラスの呼び出しを内部的に呼び出し、DefaultElementFactoryのコンストラクターはSearchContextインターフェイスオブジェクトを入力パラメーターとして受け入れます。 WebドライバーオブジェクトとWeb要素はどちらもSearchContextインターフェイスに属しています。
この場合、initElements()メソッドは、前述の要素に対してのみ事前に初期化され、Webページ上のすべての要素が初期化されるわけではありません。
#二) ただし、これは、特定の方法でAjaxElementLocatorFactoryオブジェクトを呼び出さないようにする方法を示すこの事実に対する興味深いひねりです。上記のinitElements()のバリアントをAjaxElementLocatorFactoryと一緒に使用すると、失敗します。
例: 以下のコード、つまり、ドライバーオブジェクトの代わりに要素名をAjaxElementLocatorFactory定義に渡すと、AjaxElementLocatorFactoryクラスのコンストラクターが入力パラメーターとしてWebドライバーオブジェクトのみを受け取るため、機能しなくなります。したがって、Web要素を持つSearchContextオブジェクトは機能しません。
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
Q#8)pagefactoryを使用することは、通常のページオブジェクトデザインパターンよりも実行可能なオプションですか?
回答: これは人々が持っている最も重要な質問であり、それがチュートリアルの最後でそれに対処することを考えた理由です。これで、Pagefactoryの概念、使用されるアノテーション、サポートする追加機能、コードによる実装、長所と短所から始めて、Pagefactoryの「内外」がわかりました。
それでも、pagefactoryに多くの優れた機能がある場合、なぜその使用法に固執しないのかというこの本質的な質問にとどまります。
Pagefactoryには、要素の値が頻繁に更新されるなどの動的要素では実行できない、CacheLookUpの概念が付属しています。それで、CacheLookUpのないpagefactoryは、オプションを使用するのが良いですか?はい、xpathが静的である場合。
ただし、欠点は、ページファクトリのないページオブジェクトデザインが最終的にはうまく機能することがわかっている現代のアプリケーションが重い動的要素で満たされていることですが、ページファクトリの概念は動的xpathでも同様に機能しますか?そうでないかもしれない。簡単な例を次に示します。
nseindia.comのWebページに、次のような表が表示されます。

テーブルのxpathは
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
最初の列「BuyQty」の各行から値を取得します。これを行うには、行カウンターをインクリメントする必要がありますが、列インデックスは1のままです。アノテーションは静的な値を受け入れ、変数を渡すことができないため、@ FindByアノテーションでこの動的XPathを渡す方法はありません。それ。
これは、通常のPOMがうまく機能しているのに、ページファクトリが完全に失敗する場所です。 driver.findElement()メソッドでこのような動的xpathを使用すると、forループを使用して行インデックスを簡単にインクリメントできます。
結論
ページオブジェクトモデルは、Selenium自動化フレームワークで使用される設計概念またはパターンです。
メソッドの対流に名前を付けることは、ページオブジェクトモデルでユーザーフレンドリーです。 POMのコードは、理解しやすく、再利用可能で、保守が容易です。 POMでは、Web要素に変更があった場合、すべてのクラスを編集するのではなく、それぞれのクラスで変更を加えるだけで十分です。
通常のPOMと同じようにPagefactoryは、適用するのに最適な概念です。ただし、通常のPOMが実行可能な場所と、Pagefactoryが適している場所を知る必要があります。静的アプリケーション(XPathと要素の両方が静的である)では、Pagefactoryを自由に実装でき、パフォーマンスが向上するという利点もあります。
または、アプリケーションに動的要素と静的要素の両方が含まれる場合、各Web要素の実現可能性に応じて、Pagefactoryを使用したpomとPagefactoryを使用しないpomの混合実装を使用できます。
著者:このチュートリアルはShobha Dによって作成されました。彼女はプロジェクトリーダーとして働いており、手動、自動化(Selenium、IBM Rational Functional Tester、Java)、およびAPIテスト(SOAPUIおよびJavaでの安心)で9年以上の経験があります。 。
さて、Pagefactoryのさらなる実装のためにあなたに行きましょう。
幸せな探検!!!
=> Seleniumを最初から学ぶには、ここにアクセスしてください。
推奨読書
- 30以上の最高のSeleniumチュートリアル:実際の例でSeleniumを学ぶ
- 効率的なSeleniumスクリプティングとトラブルシューティングシナリオ– Seleniumチュートリアル#27
- ログを使用したSeleniumスクリプトのデバッグ(Log4jチュートリアル)– Seleniumチュートリアル#26
- JUnitフレームワークの概要とSeleniumスクリプトでのその使用法– Seleniumチュートリアル#11
- Selenium自動化プロジェクトのテスト見積もりに影響を与える7つの要因– Seleniumチュートリアル#32
- JunitおよびTestNGフレームワークを使用したSeleniumでのアサーション
- Seleniumスクリプトを作成するためのTestNGフレームワークの使用方法-TestNGSeleniumチュートリアル#12
- SeleniumでTestNGアノテーションを使用する方法を学ぶ(例を含む)