Seleniumの自動化:ページオブジェクトモデルとページファクトリ

公開: 2022-03-11

自動化されたテストを作成することは、アジャイルソフトウェア開発チームにとって単なる贅沢ではありません。 これは必要であり、ソフトウェア開発サイクルの初期段階でバグをすばやく見つけるために不可欠なツールです。 まだ開発段階にある新機能がある場合、開発者は自動テストを実行して、システムの他の部分がそれらの変更によってどのように影響を受けるかを確認できます。 この記事では、Seleniumでページオブジェクトモデルを使用して自動テストを高速化する方法について説明します。

テストの自動化により、バグ修正のコストを削減し、ソフトウェア品質保証(QA)プロセスを全体的に改善することができます。 適切なテストを行うことで、開発者はQAに到達する前でも、バグを見つけて解決する機会を得ることができます。 テストの自動化は、絶えず後退しているテストケースと機能を自動化するのにさらに役立ちます。 このようにして、QAはアプリケーションの他の部分をテストするためにより多くの時間を費やすことができます。 さらに、これは製品リリースでの製品の品質を確保するのに役立ちます。 その結果、より効果的に安定した製品と、より効率的なQAプロセスが得られます。

Seleniumの自動化により、Webアプリケーションのテスト自動化が簡素化されます

Seleniumは、Webアプリケーションのテスト自動化を簡素化します
つぶやき

自動化されたテストを作成することは、開発者やエンジニアにとっては簡単な作業のように思えるかもしれませんが、テストの実装が不十分であり、アジャイルプロセスでのコードメンテナンスのコストが高くなる可能性があります。 アジャイル開発プロジェクトで変更や機能を絶えず提供しようとすると、テストが含まれる場合にコストがかかることが判明する可能性があります。 20のテストが依存するWebページの1つの要素を変更するには、これらの20のテストルーチンを実行し、この新しく導入された変更に適応するように各要素を更新する必要があります。 これは本当に時間がかかるだけでなく、自動テストを早期に実装することになると、やる気をなくす深刻な要因になります。

しかし、1つの場所でのみ変更を加え、関連するすべてのテストルーチンでそれを使用できるとしたらどうでしょうか。 この記事では、Seleniumでの自動​​テストと、ページオブジェクトモデルを使用して保守可能で再利用可能なテストルーチンを作成する方法について説明します。

Seleniumのページオブジェクトモデル

ページオブジェクトモデルはSeleniumのオブジェクトデザインパターンであり、Webページはクラスとして表され、ページ上のさまざまな要素はクラスの変数として定義されます。 次に、考えられるすべてのユーザーインタラクションを、クラスのメソッドとして実装できます。

 clickLoginButton(); setCredentials(user_name,user_password);

クラス内の適切な名前のメソッドは読みやすいため、これは、読みやすく、将来の保守や更新が容易なテストルーチンを実装するための洗練された方法として機能します。 例えば:

ページオブジェクトモデルをサポートするために、ページファクトリを使用します。 SeleniumのPageFactoryは、Page Objectの拡張機能であり、さまざまな方法で使用できます。 この場合、Page Factoryを使用して、Webページクラスまたはページオブジェクトで定義されているWeb要素を初期化します。

Web要素変数を使用する前に、Web要素を含むWebページクラスまたはページオブジェクトをPageFactoryを使用して初期化する必要があります。 これは、PageFactoryのinitElements関数を使用するだけで簡単に実行できます。

 LoginPage page = new LoginPage(driver); PageFactory.initElements(driver, page);

または、さらに簡単です:

 LoginPage page = PageFactory.intElements(driver,LoginPage.class)

または、Webページクラスコンストラクター内:

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

Page Factoryは、構成された「ロケーター」に基づいて、実際のWebページ上の対応する要素への参照を使用してすべてのWebElement変数を初期化します。 これは、 @FindByアノテーションを使用して行われます。 このアノテーションを使用して、要素を検索するための戦略と、要素を識別するために必要な情報を定義できます。

 @FindBy(how=How.NAME, using="username") private WebElement user_name;

このWebElement変数でメソッドが呼び出されるたびに、ドライバーは最初に現在のページでメソッドを見つけてから、相互作用をシミュレートします。 単純なページで作業している場合、ページを探すたびにその要素がページ上にあることがわかります。また、最終的にはこのページから移動して戻ってこないこともわかっています。キャッシュできます。別の単純な注釈を使用して検索されたフィールド:

 @FindBy(how=How.NAME, using="username") @CacheLookup private WebElement user_name;

WebElement変数のこの定義全体は、はるかに簡潔な形式に置き換えることができます。

 @FindBy(name="username") private WebElement user_name;

@FindByアノテーションは、物事を少し簡単にする他のいくつかの戦略をサポートします。

 id, name, className, css, tagName, linkText, partialLinkText, xpath
 @FindBy() private WebElement user_name; @FindBy(name="passsword") private WebElement user_password; @FindBy(className="h3") private WebElement label; @FindBy(css=”#content”) private WebElement text;

初期化されると、これらのWebElement変数を使用して、ページ上の対応する要素と対話できます。 たとえば、次のコードは次のようになります。

 user_password.sendKeys(password);

…指定された一連のキーストロークをページのパスワードフィールドに送信します。これは次と同等です。

 driver.findElement(By.name(“user_password”)).sendKeys(password);

次に進むと、ページ上の要素のリストを見つける必要がある状況に遭遇することがよくあります。その場合、 @FindBysが便利です。

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

上記のコードは、「yt-lockup-tile」と「yt-lockup-video」の2つのクラス名を持つすべてのdiv要素を検索します。 これを次のように置き換えることで、これをさらに単純化できます。

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

さらに、 @ FindAllと複数の@FindByアノテーションを使用して、指定されたロケーターのいずれかに一致する要素を検索できます。

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

WebページをJavaクラスとして表現し、Page Factoryを使用してWebElement変数を簡単に初期化できるようになったので、PageObjectパターンとPageFactoryを使用して簡単なSeleniumテストを作成する方法を見てみましょう。

JavaでのシンプルなSeleniumテスト自動化プロジェクト

ページオブジェクトモデルのチュートリアルでは、開発者によるToptalへのサインアップを自動化しましょう。 そのためには、次の手順を自動化する必要があります。

  • www.toptal.comにアクセス

  • 「開発者として申し込む」ボタンをクリックします

  • ポータルページで、最初に開いているかどうかを確認します

  • 「Toptalに参加」ボタンをクリックします

  • フォームに記入する

  • 「Toptalに参加」ボタンをクリックしてフォームを送信します

プロジェクトの設定

  • JavaJDKをダウンロードしてインストールします

  • InteliJIdeaをダウンロードしてインストールします

  • 新しいMavenプロジェクトを作成する

  • 「ProjectSDK」をJDKにリンクします。例:Windowsの場合「C:\ ProgramFiles \ Java\jdkxxx」

  • groupIdとartifactIdを設定します。

 <groupId>SeleniumTEST</groupId> <artifactId>Test</artifactId>
  • プロジェクトのPOMファイルに依存関係SeleniumとJUnitMavenを追加します
 <dependencies> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Selenium --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-firefox-driver</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-support</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>${selenium.version}</version> </dependency> </dependencies>

SeleniumバージョンとJUnitバージョンを、GoogleおよびSeleniumサイトでJUnitMavenを検索して見つけることができる最新のバージョン番号に置き換えます。

この時点で、自動ビルドが有効になっている場合、依存関係のダウンロードが自動的に開始されます。 そうでない場合は、IntelliJ IdeaIDEの右側にあるMavenプロジェクトパネルでプラグイン>インストール>インストール:インストールをアクティブにします。

セレンテストチュートリアルIDEスクリーンショット

プロジェクトがブートストラップされたら、「src / test/java」の下にテストパッケージの作成を開始できます。 パッケージに「com.toptal」という名前を付け、その下に「com.toptal.webpages」と「com.toptal.tests」の2つのパッケージを作成します。

セレンテストチュートリアルのスクリーンショット

ページオブジェクト/ページファクトリクラスは「com.toptal.webpages」の下に、テストルーチンは「com.toptal.tests」の下に保持します。

これで、ページオブジェクトクラスの作成を開始できます。

ホームページページオブジェクト

最初に実装する必要があるのは、Toptalのホームページ(www.toptal.com)です。 「com.toptal.webpages」の下にクラスを作成し、「HomePage」という名前を付けます。

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.How; import org.openqa.selenium.support.PageFactory; public class HomePage { private WebDriver driver; //Page URL private static String PAGE_URL="https://www.toptal.com"; //Locators //Apply as Developer Button @FindBy(how = How.LINK_TEXT, using = "APPLY AS A DEVELOPER") private WebElement developerApplyButton; //Constructor public HomePage(WebDriver driver){ this.driver=driver; driver.get(PAGE_URL); //Initialise Elements PageFactory.initElements(driver, this); } public void clickOnDeveloperApplyButton(){ developerApplyButton.click(); } }

要素ロケーターの決定

Toptalのホームページでは、特に1つの要素に関心があります。それは、「開発者として適用」ボタンです。 この要素は、テキストを照合することで見つけることができます。これは、上記で行っていることです。 Webページをページオブジェクトクラスとしてモデル化する場合、要素の検索と識別が面倒になることがよくあります。 Google ChromeまたはFirefoxのデバッグツールを使用すると、これを簡単に行うことができます。 ページ上の任意の要素を右クリックすると、コンテキストメニューから[要素の検査]オプションをアクティブにして、要素に関する詳細情報を確認できます。

一般的な(そして私の好みの)方法の1つは、FirefoxのFireBug拡張機能をSeleniumのFirefoxWebドライバーと組み合わせて使用​​して要素を見つけることです。 FireBug拡張機能をインストールして有効にした後、ページを右クリックし、[FireBugで要素を検査]を選択してFireBugを開くことができます。 FireBugの[HTML]タブから、ページ上の任意の要素のXPath、CSSパス、タグ名、または「Id」(使用可能な場合)をコピーできます。

セレンのページオブジェクトモデル:要素ロケーターの決定

上のスクリーンショットの要素のXPathをコピーすることで、次のようにページオブジェクトにその要素のWebElementフィールドを作成できます。

 @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") WebElement heading;

または、簡単にするために、関心のある要素を一意に識別する限り、ここでタグ名「h1」を使用できます。

 @FindBy(tagName = "h1") WebElement heading;

DeveloperPortalPageページオブジェクト

次に、開発者ポータルページを表すページオブジェクトが必要です。このページには、[開発者として適用]ボタンをクリックしてアクセスできます。

このページには、2つの興味深い要素があります。 ページが読み込まれたかどうかを判断するには、見出しの存在を確認します。 また、「Toptalに参加」ボタン用のWebElementフィールドも必要です。

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperPortalPage { private WebDriver driver; @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") private WebElement heading; @FindBy(linkText = "JOIN TOPTAL") private WebElement joinToptalButton; //Constructor public DeveloperPortalPage (WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } //We will use this boolean for assertion. To check if page is opened public boolean isPageOpened(){ return heading.getText().toString().contains("Developer portal"); } public void clikOnJoin(){ joinToptalButton.click(); } }

DeveloperApplyPageページオブジェクト

最後に、このプロジェクトの3番目で最後のページオブジェクトに対して、開発者アプリケーションフォームを含むページを表すオブジェクトを定義します。 ここでは多数のフォームフィールドを処理する必要があるため、フォームフィールドごとに1つのWebElement変数を定義します。 各フィールドは「id」で検索し、対応するフィールドのキーストロークをシミュレートするすべてのフィールドに特別なセッターメソッドを定義します。

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperApplyPage { private WebDriver driver; @FindBy(tagName = "h1") WebElement heading; @FindBy() WebElement developer_email; @FindBy() WebElement developer_password; @FindBy() WebElement developer_password_confirmation; @FindBy() WebElement developer_full_name; @FindBy() WebElement developer_skype; @FindBy() WebElement join_toptal_button; //Constructor public DeveloperApplyPage(WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } public void setDeveloper_email(String email){ developer_email.clear(); developer_email.sendKeys(email); } public void setDeveloper_password(String password){ developer_password.clear(); developer_password.sendKeys(password); } public void setDeveloper_password_confirmation(String password_confirmation){ developer_password_confirmation.clear(); developer_password_confirmation.sendKeys(password_confirmation); } public void setDeveloper_full_name (String fullname){ developer_full_name.clear(); developer_full_name.sendKeys(fullname); } public void setDeveloper_skype (String skype){ developer_skype.clear(); developer_skype.sendKeys(skype); } public void clickOnJoin(){ join_toptal_button.click(); } public boolean isPageOpened(){ //Assertion return heading.getText().toString().contains("Apply to join our network as a developer"); } }

簡単なSeleniumテストの作成

ページを表すPageObjectクラスと、それらのメソッドとしてのユーザーインタラクションを使用して、一連の単純なメソッド呼び出しとアサーションとして単純なテストルーチンを記述できるようになりました。

 package com.toptal.tests; import com.toptal.webpages.DeveloperApplyPage; import com.toptal.webpages.DeveloperPortalPage; import com.toptal.webpages.HomePage; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import java.net.URL; import java.util.concurrent.TimeUnit; public class ApplyAsDeveloperTest { WebDriver driver; @Before public void setup(){ //use FF Driver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void applyAsDeveloper() { //Create object of HomePage Class HomePage home = new HomePage(driver); home.clickOnDeveloperApplyButton(); //Create object of DeveloperPortalPage DeveloperPortalPage devportal= new DeveloperPortalPage(driver); //Check if page is opened Assert.assertTrue(devportal.isPageOpened()); //Click on Join Toptal devportal.clikOnJoin(); //Create object of DeveloperApplyPage DeveloperApplyPage applyPage =new DeveloperApplyPage(driver); //Check if page is opened Assert.assertTrue(applyPage.isPageOpened()); //Fill up data applyPage.setDeveloper_email("[email protected]"); applyPage.setDeveloper_full_name("Dejan Zivanovic Automated Test"); applyPage.setDeveloper_password("password123"); applyPage.setDeveloper_password_confirmation("password123"); applyPage.setDeveloper_skype("automated_test_skype"); //Click on join //applyPage.clickOnJoin(); } @After public void close(){ driver.close(); } }

テストの実行

この時点で、プロジェクト構造は次のようになります。

セレンのテスト例

テストを実行する場合は、ツリーから「ApplyAsDeveloperTest」を選択し、それを右クリックして、 「実行」「ApplyAsDeveloperTest」を選択します。

セレンのテスト例

テストが実行されると、IDEの左下隅に結果が表示されます。

セレンのテスト例

結論

PageObjectとPageFactoryを使用すると、SeleniumでWebページを簡単にモデル化して自動的にテストし、開発者とQAの両方の作業をはるかに簡単にすることができます。 正しく実行すると、これらのページオブジェクトクラスをテストスイート全体で再利用でき、アジャイル開発を損なうことなく、プロジェクトの自動Seleniumテストを早い段階で実装する機会を得ることができます。 ページオブジェクトモデルでのユーザーインタラクションを抽象化し、テストルーチンを軽量かつシンプルに保つことで、わずかな労力でテストスイートを要件の変化に適応させることができます。

メンテナンスが簡単で、きれいできれいなテストコードを書く方法をお見せできたと思います。 私のお気に入りのQA引用で記事を終了します:

よく考えて、一度コーディングしてください!

関連:ヘッドレスブラウザを使用したWebスクレイピング:Puppeteerチュートリアル