web-dev-qa-db-ja.com

Seleniumでのページオブジェクトモデルのベストプラクティス

ページオブジェクトをモデル化する場合、フォームと約50の入力フィールドがあるページをどのように処理しますか?ここでのベストプラクティスは何ですか?

ページオブジェクトを作成し、入力アクションごとに個別の関数を記述しますか?または、パラメータが渡されてテキストを入力する1つの関数を記述しますか?

例えば.

public void enterFirstName(String firstName) {
    driver.type("firstNameField", firstName);
}

public void enterSecondName(String secondName) {
    driver.type("secondNameField", secondName);
}

または

public void fillInForm(String inputFieldName, String text) {
    driver.type(inputFieldName, text);
}

最初のモデルでわかるように、テストを作成するとき、テストはより説明的ですが、ページに含まれる入力フィールドが多すぎると、ページオブジェクトの作成が面倒になります。

この投稿は、ページオブジェクトでのSeleniumテストの構造化にも非常に興味深いものです Selenium WebDriverを使用した機能的な自動テストのベストプラクティス

23
Amir Ghahrai

私はいつも物事を関連情報のグループに分割するのが好きです。たとえば、ユーザークラスがある場合、LoginCredentials、ProfileInfo、Settingsなどのいくつかの小さなクラスに分割できますが、通常は、これらのサブクラスを含むトップレベルのユーザークラスがあります。

私が確かにお勧めすることの1つは、オブジェクトを個々の関数すべてではなく、1つのFillForm関数に渡すことです。このアプローチを使用すると、いくつかの大きな利点があります。 1つは、多くのテストケースで使用する「一般的な」事前構成済みオブジェクトをいくつか持つことができます。例えば:

public class FormInfo
{
   string Domain;
   string Name;
   string Category;
   // etc...

  public FormInfo(string domain, string name, string category)
  {
     Domain = domain;
     Name = name;
     Category = category;
     // etc...
  }
}


// Somewhere in your initialization code
public static FormInfo Info1 = new FormInfo("myDomain1", "myName1", "myCategory1");
public static FormInfo Info2 = new FormInfo("myDomain2", "myName2", "myCategory2");

You can still update one of your common merchants if you need to do something one-off:

// In your test case:
Info1.Category = "blah";
FormPage.FillForm(Info1);

または、必要に応じて、特定のテストケース用の新しいマーチャントオブジェクトを作成できます。これらのオブジェクトを使用してフィールド検証などを行うこともできます。または、通常行うことは、特定のフィールド検証のためにページオブジェクトパターンを分割することです。したがって、マーチャントドメインフィールドを検証する場合は、次のようにします。

Info1.Domain = null; //This should make the FillForm function skip doing anything with this field.
FormPage.FillForm(Info1);
FormPage.DomainTextBox.Text = "field validation string";

このアプローチのもう1つの重要な利点は、フィールドを追加、削除、または変更するためにページが更新された場合、FormInfoオブジェクトとFillForm関数を更新するだけでよく、FillForm関数を呼び出す特定のテストケースを変更する必要がないことです。一般的なFormInfoオブジェクトの1つを使用していると仮定します。より多くのカバレッジを取得する別の可能性は、共通のFormInfoオブジェクトの1つを設定して、許可されたすべての異なる文字間の最小/最大長とサイクルに準拠するフィールドごとにランダムな文字列を生成することです。これにより、同じテストセットからいくつかの追加テストを取得できますが、特定の文字列からのみ失敗結果を取得し始めるとノイズが追加される可能性があるため、注意してください。

9
Sam Woods

ページオブジェクトモデルの背後にある考え方は、呼び出し元から実装を抽象化することです。最初のメカニズムでは、呼び出し元がhtml入力フィールド名が「firstName」から「user_first_name」に変更されたかどうかを知る必要がないため、これを正常に実行できますが、2番目の実装では、実際のページへの変更は次のようになります。ページオブジェクトのすべての呼び出し元にだまされました。

ページオブジェクトを作成するのは前もって手間がかかるかもしれませんが、カプセル化を維持すると、実際のhtmlページが必然的に変更されたときに長期的に作業を節約できます。

10
digitaljoel

私は読者の利益のために古い質問に答えています。

ここに他の良い答えとともに、POMに不慣れな人のためにここにいくつかの提案を追加したいと思います。

ページオブジェクトは、自動化エンジニアによって広く受け入れられているよく知られたデザインパターンであり、アプリケーションのページごとに個別のクラスファイルを作成して、すべての要素をプロパティとしてグループ化し、それらの動作/ビジネス機能をクラスのメソッドとしてグループ化します。ただし、ページのクラスを作成する際の問題はほとんどありません。特に、ページに、グリッド/カレンダーウィジェット/ HTMLテーブルなどのより多くの/異なる要素のセット/複雑な要素がある場合はそうです。

クラスには、処理するには多すぎる責任が含まれている可能性があります。再構築して、より小さなクラスに分割する必要があります。つまり、Single Responsibility Responsibleに続く

こちらの画像でアイデアを確認してください。

enter image description here

つまり、再利用可能なページフラグメントを作成し、メインページオブジェクトにページフラグメントを提供させます。

詳細については、 ここ を確認してください。

1
vins

enterWhatever()メソッドに加えて、私は通常createWhatever(field1, field2, ...)メソッドも作成します。これは、フォームが作成するものを作成するための高速パスとして使用でき、realテストの目的は別のものです。したがって、チケットの送信をテストするために顧客を作成する必要がある場合、テストはCreateACustomerページに移動し、createCustomer(firstName, lastName, emailAddress, ...)を呼び出すだけで、より微妙なタスクに進みます。その顧客を使用してチケットを作成します。

1
Ross Patterson
0
Yujun Liang

フォームでこれを行う方法は、ページ上のすべての入力のリストを取得することです。次に、表示されていない入力要素をすべて削除します。その後、有効または無効なテキストを各入力に入力できます。そこから、検証の要約をキャッチして、正しいエラーが発生しているかどうかを確認します。そうでない場合は、例外をログに記録します。

これにより、ページにあるのと同じ数の入力にテキストを入力できるようになりますが、それでも例外をログに記録して電子メールで送信できます。また、リスト内のテキストエリアとパスワードフィールドをキャッチし、チェックボックスフィールドとオプション用に個別のリストを用意しています。

要約すると、ページをテストするために私がしなければならないのはこれだけです。

for (int i = 0; i < inputs.Count(); i++)
{
  //This captures the error message string created in the input validation method
  //nextButton is the IWebElement of the button to click to submit the form for validation
  //ErrorMessageID is the ID of the Validation Summary display box (i.e. ErrorMessageID = "FormSummary" <asp:ValidationSummary ID="FormSummary" runat="server" CssClass="errorMessage" />

  string InputValidationText = utilities.InputValidation(driver, inputs, i, nextButton, ErrorMessageID)
  if(InputValidationText != string.Empty)
  {
    //LogError
  }
}
0
CBRRacer