なぜ_@FindBy
_ vs driver.findElement()
を使用する必要があるのですか?
_@FindBy
_は、すべての変数をクラスレベルに移動することを強制します(ほとんどの変数がメソッドレベルである必要がある場合)。私を買うように思える唯一のものは、PageFactory.initElements()
を呼び出すことができることです。
私は何が欠けていますか?
大まかに言うと、_@FindBy
_は要素を見つけるための代替方法にすぎません(「通常の方法」はdriver.findElement()
でした)。
ただし、このアノテーションの大きな利点はそれ自体ではありません。 PageObjectパターンをサポートするために使用する方が適切です。
簡単に言うと、PageObjectパターンは、システムの各ページにクラスを作成するよう指示します使用/テストしようとしています。
したがって、(通常のdriver.findElement()
コード)の代わりに:
_public class TestClass {
public void testSearch() {
WebDriver driver = new HtmlUnitDriver();
driver.get("http://www.google.com/");
Element searchBox = driver.findElement(By.name("q"));
searchBox.sendKeys("stringToSearch");
searchBox.submit();
// some assertions here
}
}
_
ページのクラスを定義します(使用する要素に_@FindBy
_注釈を付けます):
_public class GooglePage {
@FindBy(how = How.NAME, using = "q")
private WebElement searchBox;
public void searchFor(String text) {
searchBox.sendKeys(text);
searchBox.submit();
}
}
_
そして次のように使用します:
_public class TestClass {
public void testSearch() {
WebDriver driver = new HtmlUnitDriver();
driver.get("http://www.google.com/");
GooglePage page = PageFactory.initElements(driver, GooglePage.class);
page.searchFor("stringToSearch");
// some assertions here
}
}
_
今、私はこれが最初は冗長に見えるかもしれませんが、少し時間を置いて、そのページのいくつかのテストケースを持つことを検討してください。 searchBox
の名前が変わったらどうなりますか? (name
_"q"
_からid
へ、たとえばquery
?と言います)
どのコードで、それを再び動作させるためにさらに変更がありますか?ページオブジェクト(および_@FindBy
_)のあるものとないものページの構造が大幅に変更された場合、どのコードでメンテナンスが簡単になりますか?
次のような追加の注釈など、他にもいくつかの利点があります。
_@FindBy(name = "q")
@CacheLookup
private WebElement searchBox;
_
_@CacheLookup
_は、要素の検索を一度だけ実行します。その後、変数にキャッシュされ、より速くアクセスできるようになります。
お役に立てれば。詳細については、PageFactoryおよびPageObjectパターン。
@FindByアノテーションは、IntelliJがその変数が使用されているかどうかを検出しなくなり、クリーンアップするのが面倒になるため、好きではありません。
簡単に言えば、_@FindBy
_とdriver.findElement()
は両方とも、異なる Locator Strategies を通じて要素を見つけるための異なるアプローチです。
PageFactoryを使用する場合、 注釈タイプFindBy を使用できます。 FindBy注釈は、一般的に次の形式で使用するboiler-plateコードを削除するのに役立ちますfindElement()
およびfindElements()
要素を検索する場合。
例として:
_WebElement element = driver.findElement(By.name("q"));
element.click();
_
になる:
_element.click();
_
ディスカッション内の同じトピックに関する@Simon Stewartのコメントを見つけることができます PageFactoryフィールドとPageObjectパターンで明示的な待機を使用する方法
import org.openqa.Selenium.WebElement;
import org.openqa.Selenium.support.FindBy;
public class CommonPageForStudent {
@FindBy(name="usname")
private WebElement Studentusername;
@FindBy(name="pass")
private WebElement Studentpassword;
@FindBy(xpath="//button[@type='submit']")
private WebElement StudentLetmein;
@FindBy(id="logoutLink")
private WebElement StudentlogoutLnk;
public void loginToStudent(String username , String password ){
Studentusername.sendKeys(username);
Studentpassword.sendKeys(password);
StudentLetmein.click();
}
//when you call this methods from another class write this 2 line code that class
//CommonPageForStudent page = PageFactory.initElements(driver, CommonPageForStudent.class);
// page.loginToStudent("","");
public void logOut(){
StudentlogoutLnk.click();
}
//page.logOut(); method call
}`
Page Factoryを使用する利点の1つは、StaleElementExceptionを回避できることです。以下のリンクをご覧ください:
ページオブジェクトモデルがStaleElementReferenceExceptionを解決する方法
上記のリンクからの抜粋:
ページオブジェクトデザインパターンを使用すると、プログラムが正常に実行されます。古い要素参照の例外は発生しません。 POMでFindByアノテーションを使用すると、webdriverはエレメントを見つけ、アクションを実行する前に毎回参照を更新します。どこでも再配置せずにWeb要素を使用できます。これは、ページオブジェクトモデルを使用する主な利点です。
古い要素との戦いと回避方法
上記のリンクからの抜粋:
古くなった要素と戦い、回避する方法
Web上の古い要素の例外を処理する方法はたくさんあります。ここで、私が個人的に最も役に立つと思うものを集めました。
遅延初期化のために@FindByアノテーションを使用することをお勧めします。これにより、実際の使用の直前に要素が初期化されます。例:@FindBy(xpath =” someXpath”)public WebElement someElement;
JavaScript、Ajax、Jqueryなどの待機メソッドを使用します。これにより、この例外が発生する「レース状態」が解決されます。