Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium @FindBy vs driver.findElement()

Why should I use @FindBy vs driver.findElement()?

@FindBy forces me to move all my variables to a class level (when most of them only need to be at the method level). The only thing it seems to buy me is I can call PageFactory.initElements(), which handles lazy initialization for me.

What am I missing?

like image 330
pyrrhicVictory Avatar asked Aug 26 '13 03:08

pyrrhicVictory


People also ask

What is Selenium driver findElement?

Selenium WebDriver defines two methods for identifying the elements, they are findElement and findElements . findElement: This command is used to uniquely identify a web element within the web page. findElements: This command is used to uniquely identify the list of web elements within the web page.

What is the difference between WebDriver findElement and WebElement findElement?

There are differences between findElement and findElements in the Selenium webdriver. Both of them can be used to locate elements on a webpage. The findElement points to a single element, while the findElements method returns a list of matching elements.

What is the difference between driver findElement () and driver findElements ()?

driver. findElement() returns first matching element with specified locator and driver. findElements() returns all(array of) matching elements with specified locator.

What is @FindBy annotation in Selenium?

Annotation Type FindBy Used to mark a field on a Page Object to indicate an alternative mechanism for locating the element or a list of elements. Used in conjunction with PageFactory this allows users to quickly and easily create PageObjects. It can be used on a types as well, but will not be processed by default.


2 Answers

Roughly speaking, @FindBy is just an alternate way of finding elements (the "usual way" being driver.findElement() as you said).

The big advantage of that annotation is not itself, though. It is better used to support the PageObject pattern.

In a few words, the PageObject pattern tells you to create a class for each page of the system you are trying to use/test.

So, instead of having (the usual driver.findElement() code):

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     } }  

You'd define a class for the page (with the @FindBy annotation for the elements used):

public class GooglePage {     @FindBy(how = How.NAME, using = "q")     private WebElement searchBox;     public void searchFor(String text) {         searchBox.sendKeys(text);         searchBox.submit();     } } 

And use it like:

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     } }  

Now, I know this may seem verbose at first, but just give it a moment and consider having several tests cases for that page. What if the name of the searchBox changes? (From the name "q" to an id, say query?)

In what code there would be more changes to make it work again? The one with or the one without the Page Objects (and @FindBy)? If a page changes its structure a lot, in what code the maintenance would be easier?

There are some other advantages, such as additional annotations like:

@FindBy(name = "q") @CacheLookup private WebElement searchBox; 

That @CacheLookup makes the lookup for the element happen just once. After that, it will be cached in the variable and accessible much faster.

Hope this helps. For more details, make sure to check PageFactory and the PageObject pattern.

like image 143
acdcjunior Avatar answered Oct 01 '22 01:10

acdcjunior


I don't like @FindBy annotations because then IntelliJ no longer detects if that variable is being used, makes it a pain to clean up.

like image 24
1ak31sha Avatar answered Oct 01 '22 01:10

1ak31sha