Selenium @FindBy vs driver.findElement()

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.


In simple words, both @FindBy and driver.findElement() are different approach to locate element/s through different Locator Strategies.

When using PageFactory we can use the Annotation Type FindBy. The FindBy annotations helps us to remove the boiler-plate code which we generally use in the form of findElement() and findElements() when looking for elements.

As an example:

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

becomes:

element.click();

You can find @Simon Stewart's comments on the same topic within the discussion How to use explicit waits with PageFactory fields and the PageObject pattern


References

You can find a couple of relevant detailed discussion in:

  • Difference between @By and @FindBy in POM using Selenium