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?
One of the advantages of using Page Factory is, it can avoid StaleElementException. Please see the below link:
How Page Object Model solves StaleElementReferenceException?
Excerpts from the above link:
How to fight and avoid Stale Elements.
Excerpts from the above link:
I see one more advantage to use @FindBy. When you have two methods in the same class which have the same name, only return different page objects and passed parameter: driver. Then you can use in PageObject:
Test method:
In simple words, both
@FindBy
anddriver.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()
andfindElements()
when looking for elements.As an example:
becomes:
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
Roughly speaking,
@FindBy
is just an alternate way of finding elements (the "usual way" beingdriver.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):You'd define a class for the page (with the
@FindBy
annotation for the elements used):And use it like:
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 thename
"q"
to anid
, sayquery
?)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:
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.
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.