Selenium @FindBy vs driver.findElement()
annotations, findby, page-factory, selenium, selenium-webdriver
Solution
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.
Problem
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?