Selenium @FindBy vs driver.findElement()

时间:2013-08-26 03:15:38

标签: selenium selenium-webdriver annotations findby page-factory

我为什么要使用@FindBy vs driver.findElement()

@FindBy迫使我将所有变量移动到类级别(当大多数变量只需要处于方法级别时)。它似乎唯一给我买的是我可以调用PageFactory.initElements(),它为我处理延迟初始化。

我错过了什么?

6 个答案:

答案 0 :(得分:49)

粗略地说,@FindBy只是寻找元素的另一种方式(正常方式是driver.findElement(),如你所说)。

然而,该注释的最大优势本身并非如此。它最好用于支持 PageObject pattern

简而言之, 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 pattern

答案 1 :(得分:3)

我不喜欢@FindBy注释,因为IntelliJ不再检测是否正在使用该变量,这使得清理很麻烦。

答案 2 :(得分:1)

简单地说,@FindBydriver.findElement()都是通过不同的Locator Strategies来定位元素的不同方法。

使用PageFactory时,我们可以使用Annotation Type FindBy FindBy 注释可帮助我们删除在查找元素时通常以findElement()findElements()形式使用的样板代码。

例如:

WebElement element = driver.findElement(By.name("q"));
element.click();

成为:

element.click();

您可以在讨论How to use explicit waits with PageFactory fields and the PageObject pattern

中找到@Simon Stewart对同一主题的评论

答案 3 :(得分:0)

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

}`

答案 4 :(得分:0)

我看到使用@FindBy的另一个优势。 当同一类中有两个名称相同的方法时,仅返回不同的页面对象和传递的参数:driver。 然后可以在PageObject中使用:

public <T extends TestingEnvironment > T clickAction(Class<T> expectedPage){
            element.click();
            return PageFactory.initElements(driver, expectedPage);
        }

测试方法:

public void Test() {
        TestingEnvironment testingEnvironment = PageFactory.initElements(driver, TestingEnvironment.class);

        testingEnvironment.openPage();

        Patient patient = testingEnvironment.logIn();

        Reason reason = patient.clickAction(Reason.class);
        //You also can assing:
        NewReason newReason =  patient.clickAction(NewReason.class);

    }

答案 5 :(得分:-1)

使用Page Factory的优点之一是,它可以避免 StaleElementException 。 请参见以下链接:

How Page Object Model solves StaleElementReferenceException?

上述链接的摘录:

  

当我们使用页面对象设计模式时,您将看到程序运行良好。   您将永远不会获得Stale Element Reference Exception。当我们使用   通过POM中的FindBy注释,Webdriver可以定位元素并进行更新   每次对它执行任何操作之前都要进行引用。您可以使用   Web元素,而无需将其放置在任何位置。这是主要优势   使用页面对象模型。   


How to fight and avoid Stale Elements.

上述链接的摘录:

  

如何战斗和避免陈旧元素

     

有许多方法可以处理   网络。在这里,我收集了我个人认为最有用的内容。

     

由于懒惰,一种好的做法是使用@FindBy注释   初始化这样,元素将在之前被初始化   实际使用情况。示例:@FindBy(xpath =“ someXpath”)public WebElement   someElement;

     

对JavaScript,Ajax,Jquery等使用等待方法。这将解决   导致此异常发生的“种族条件”。