Resource library

QA How-To

How to Use Selenium PageFactory and FindBy in Java (2026)

Learn selenium PageFactory and FindBy java patterns with runnable examples, locator strategies, waits, testing advice, and practical interview-ready answers.

16 min read | 3,005 words

TL;DR

`PageFactory.initElements` decorates eligible fields. A `@FindBy` field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures. Use the runnable pattern in this guide, then adapt locators and readiness conditions to the application contract.

Key Takeaways

  • Use official Selenium APIs and verify language-specific names before designing wrappers.
  • Separate element identification from the condition that makes the next action safe.
  • Keep page and component APIs behavior-focused so tests do not depend on DOM details.
  • Reacquire dynamic elements after rerenders instead of retaining stale references.
  • Isolate drivers, data, and artifacts for reliable parallel execution.
  • Capture actionable evidence before changing locators, waits, or retry policy.

The selenium PageFactory and FindBy java pattern initializes page object fields as Selenium element proxies, letting a test describe page structure with annotations instead of repeating findElement calls. It remains available in Selenium 4, but it is optional: modern teams should combine it with explicit waits, small page APIs, and carefully chosen locators rather than treating annotations as a complete framework.

This guide builds a runnable Maven example, explains proxy timing and annotation behavior, and shows where plain By locators are clearer. The goal is not to promote one style blindly. It is to help you make a defensible design choice and explain that choice in a senior SDET interview.

TL;DR

Question Practical answer
What should you use? Use the official Selenium API shown in this guide.
What improves reliability? Stable locators, explicit readiness conditions, isolated state, and useful artifacts.
What should you avoid? Sleeps, hidden global drivers, brittle positional selectors, and unexplained retries.

The central rule is simple: make location, synchronization, and test intent visible enough to review.

1. What Selenium PageFactory and FindBy Java Actually Do

PageFactory.initElements decorates eligible fields. A @FindBy field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures.

Start from the user-visible behavior, then choose the smallest Selenium mechanism that proves it. For selenium PageFactory and FindBy java, readability is an engineering control: a reviewer should understand the anchor, action, and expected state without opening several helpers.

Treat rerendering as normal in modern applications. Store durable locator definitions, reacquire elements after state changes, and avoid keeping WebElement references across navigation, filtering, modal transitions, or component replacement.

Field note 1

In a real project, PageFactory.initElements decorates eligible fields. A @FindBy field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures. Before changing code, reproduce the behavior in the supported browser and capture the exact page state. Compare a passing and failing run, then make one controlled change. This approach protects the suite from speculative fixes and gives reviewers a clear causal story.

A useful team exercise is to pair on the failure and ask three questions: what contract did the test assume, what evidence proves that contract changed, and which layer should own the correction? The answer may belong in product markup, page synchronization, test data, or environment configuration. Documenting that decision prevents the next engineer from rebuilding the same workaround.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

2. Project Setup for Selenium PageFactory and FindBy Java

Use a normal Selenium Java dependency, a test framework such as JUnit Jupiter, and a browser driver resolved by Selenium Manager. PageFactory and FindBy live in Selenium support packages, so no separate PageFactory library is required.

A reliable implementation separates identification from readiness. The locator identifies a candidate, while a wait confirms the condition required by the next action. This separation makes a timeout explainable and prevents arbitrary sleep values from becoming framework policy.

For debugging, preserve the locator or relation, current URL, screenshot, stack trace, browser metadata, and relevant DOM evidence. If multiple candidates are possible, inspect all of them before making the selector longer.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

3. Build a Complete Login Page Object

A page object should expose user intent such as loginAs, not every underlying element. Initialization belongs in the constructor, while navigation, synchronization, and state reading remain explicit methods.

Treat rerendering as normal in modern applications. Store durable locator definitions, reacquire elements after state changes, and avoid keeping WebElement references across navigation, filtering, modal transitions, or component replacement.

For maintainability, keep browser details inside a page or component API and keep assertions focused on business outcomes. This gives the team one repair point when markup changes and keeps test intent useful to developers and product owners.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

4. Choose the Right FindBy Locator

Prefer stable IDs, meaningful test attributes, accessible relationships, or concise CSS. XPath is valid when the relationship cannot be expressed cleanly otherwise, but positional XPath and visual-class chains are fragile.

For debugging, preserve the locator or relation, current URL, screenshot, stack trace, browser metadata, and relevant DOM evidence. If multiple candidates are possible, inspect all of them before making the selector longer.

In code review, ask whether the mechanism is part of official Selenium, whether the candidate is unique, whether synchronization describes real readiness, and whether parallel workers share state. Those questions catch more risk than a formatting-only review.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

5. Understand Proxies, Caching, and Stale Elements

Without @CacheLookup, PageFactory proxies generally locate on use. @CacheLookup stores the element and is unsafe for nodes that a framework rerenders. A cached reference can become stale even though the screen looks unchanged.

For maintainability, keep browser details inside a page or component API and keep assertions focused on business outcomes. This gives the team one repair point when markup changes and keeps test intent useful to developers and product owners.

Start from the user-visible behavior, then choose the smallest Selenium mechanism that proves it. For selenium PageFactory and FindBy java, readability is an engineering control: a reviewer should understand the anchor, action, and expected state without opening several helpers.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

6. Synchronize with Explicit Waits

Annotations locate elements, but they do not define business readiness. Wait for the condition the next action needs, such as visibility, clickability, URL change, or a result row that contains expected text.

In code review, ask whether the mechanism is part of official Selenium, whether the candidate is unique, whether synchronization describes real readiness, and whether parallel workers share state. Those questions catch more risk than a formatting-only review.

A reliable implementation separates identification from readiness. The locator identifies a candidate, while a wait confirms the condition required by the next action. This separation makes a timeout explainable and prevents arbitrary sleep values from becoming framework policy.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

7. Model Lists, Frames, and Components

@FindBy can decorate List<WebElement>, but tests should not manipulate that list directly. Wrap repeated widgets in component objects, switch frames deliberately, and return stable domain values.

Start from the user-visible behavior, then choose the smallest Selenium mechanism that proves it. For selenium PageFactory and FindBy java, readability is an engineering control: a reviewer should understand the anchor, action, and expected state without opening several helpers.

Treat rerendering as normal in modern applications. Store durable locator definitions, reacquire elements after state changes, and avoid keeping WebElement references across navigation, filtering, modal transitions, or component replacement.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

8. Compare PageFactory with Plain By Locators

Plain By fields make lookup and waits explicit. PageFactory reduces field boilerplate. Both can support a good Page Object Model, and consistency plus behavior-focused APIs matter more than annotation count.

A reliable implementation separates identification from readiness. The locator identifies a candidate, while a wait confirms the condition required by the next action. This separation makes a timeout explainable and prevents arbitrary sleep values from becoming framework policy.

For debugging, preserve the locator or relation, current URL, screenshot, stack trace, browser metadata, and relevant DOM evidence. If multiple candidates are possible, inspect all of them before making the selector longer.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

9. Test Page Objects Without Hiding Failures

Keep assertions in tests except for page invariants. Capture enough failure context, avoid catch-and-retry wrappers, and make methods return the next page or a meaningful result when navigation occurs.

Treat rerendering as normal in modern applications. Store durable locator definitions, reacquire elements after state changes, and avoid keeping WebElement references across navigation, filtering, modal transitions, or component replacement.

For maintainability, keep browser details inside a page or component API and keep assertions focused on business outcomes. This gives the team one repair point when markup changes and keeps test intent useful to developers and product owners.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

10. Refactor a Brittle PageFactory Class

Remove public elements, eliminate Thread.sleep, replace broad XPath, and split oversized screens into components. Refactoring should preserve test intent while reducing the number of DOM details visible to callers.

For debugging, preserve the locator or relation, current URL, screenshot, stack trace, browser metadata, and relevant DOM evidence. If multiple candidates are possible, inspect all of them before making the selector longer.

In code review, ask whether the mechanism is part of official Selenium, whether the candidate is unique, whether synchronization describes real readiness, and whether parallel workers share state. Those questions catch more risk than a formatting-only review.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

11. Use Selenium PageFactory and FindBy Java in a Framework

Create drivers per test or worker, inject them into pages, and quit them reliably. Do not store a driver or page object in a mutable static field because parallel tests will race.

For maintainability, keep browser details inside a page or component API and keep assertions focused on business outcomes. This gives the team one repair point when markup changes and keeps test intent useful to developers and product owners.

Start from the user-visible behavior, then choose the smallest Selenium mechanism that proves it. For selenium PageFactory and FindBy java, readability is an engineering control: a reviewer should understand the anchor, action, and expected state without opening several helpers.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

12. Decide When Not to Use PageFactory

Skip PageFactory when the team values explicit lookup, uses highly dynamic component trees, or wants immutable locator definitions. Selenium does not require PageFactory, and a conventional page object using By is fully supported.

In code review, ask whether the mechanism is part of official Selenium, whether the candidate is unique, whether synchronization describes real readiness, and whether parallel workers share state. Those questions catch more risk than a formatting-only review.

A reliable implementation separates identification from readiness. The locator identifies a candidate, while a wait confirms the condition required by the next action. This separation makes a timeout explainable and prevents arbitrary sleep values from becoming framework policy.

Practical review checklist

  • Confirm the selector or anchor is unique in the supported states.
  • Wait for a meaningful condition instead of elapsed time.
  • Keep driver and data ownership safe for parallel execution.
  • Return a page, component, or domain value rather than exposing internals.
  • Capture diagnostic artifacts before cleanup removes the failing state.

Reference Comparison

Approach Strength Main risk Good fit
@FindBy proxy Compact fields Timing can look implicit Stable forms and team convention
Plain By Explicit lookup and waits More code Dynamic pages and precise synchronization
@CacheLookup Avoids repeated lookup Stale references Truly static nodes only
Component object Encapsulates repeated UI More types Design systems and complex screens

Use the table as a decision aid, not an automatic ranking. Product markup, browser matrix, team ownership, and failure cost determine which option is appropriate. Record unusual choices next to the page component or in a short architecture note so future maintainers know the reason.

Interview Questions and Answers

These model answers are intentionally concise. In an interview, add one real example, the evidence you inspected, and the tradeoff you accepted.

Q: What is the key fact about selenium PageFactory and FindBy java?

PageFactory.initElements decorates eligible fields. A @FindBy field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures. The best answer also states its limitations and how synchronization remains explicit.

Q: When would you use selenium PageFactory and FindBy java?

A page object should expose user intent such as loginAs, not every underlying element. Initialization belongs in the constructor, while navigation, synchronization, and state reading remain explicit methods. I would use it only when that convention makes intent clearer for the team.

Q: What is the biggest reliability risk?

Without @CacheLookup, PageFactory proxies generally locate on use. @CacheLookup stores the element and is unsafe for nodes that a framework rerenders. A cached reference can become stale even though the screen looks unchanged. I reduce that risk with stable locators, explicit conditions, and evidence-rich failures.

Q: How would you review this implementation?

I verify API authenticity, locator uniqueness, wait boundaries, encapsulation, and parallel safety. I also ask whether a simpler official Selenium pattern communicates the same intent.

Q: Why should a page object hide WebElements?

Hiding WebElements keeps tests focused on behavior and limits DOM knowledge to one layer. It also lets the page object add synchronization and return domain values without changing every caller.

Q: Should implicit and explicit waits be mixed?

Mixing them can produce confusing timeout behavior because element lookup time contributes to explicit wait polling. Use an explicit, documented synchronization strategy and keep implicit wait at zero or a consciously chosen minimal value.

Q: How do you make a locator maintainable?

Start with a stable product contract such as an ID, accessible relationship, or dedicated test attribute. Keep it concise, ensure it is unique, and avoid indexes or styling classes that change during redesign.

Q: What belongs in a UI automation failure report?

Include the assertion, stack trace, URL, screenshot, browser and driver details, and relevant logs. For parallel execution, attach artifacts to the exact test and use unique filenames.

Common Mistakes

  • Copying an API from another language or a third-party package without checking its source.
  • Using Thread.sleep or time.sleep as the primary synchronization strategy.
  • Keeping a WebElement across a navigation or component rerender.
  • Exposing locators and elements publicly so every test depends on markup.
  • Using generated CSS classes, deep DOM chains, or positional XPath without a clear reason.
  • Sharing a mutable driver, page, account, or download path between parallel workers.
  • Catching Selenium exceptions and returning a generic boolean that destroys diagnostic context.
  • Increasing a timeout before proving that readiness, rather than identity, is the problem.

A practical correction sequence is to reproduce once with artifacts, classify the failure, reduce the page contract, and add the narrowest condition that reflects user-observable readiness. The related reading in Selenium waits in Java, Page Object Model interview questions, Selenium stale element fixes provides deeper treatment of waits, locators, and framework design.

Conclusion

selenium PageFactory and FindBy java is most useful when it expresses a stable contract and remains easy to diagnose. Use the official API accurately, keep page behavior behind small methods, synchronize against observable state, and preserve evidence when a test fails.

As a next step, run the example against a small practice page, deliberately trigger a rerender or responsive change, and inspect the failure artifacts. That exercise turns syntax knowledge into the engineering judgment expected from a working QA or SDET.

Interview Questions and Answers

What is the key fact about selenium PageFactory and FindBy java?

`PageFactory.initElements` decorates eligible fields. A `@FindBy` field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures. The best answer also states its limitations and how synchronization remains explicit.

When would you use selenium PageFactory and FindBy java?

A page object should expose user intent such as `loginAs`, not every underlying element. Initialization belongs in the constructor, while navigation, synchronization, and state reading remain explicit methods. I would use it only when that convention makes intent clearer for the team.

What is the biggest reliability risk?

Without `@CacheLookup`, PageFactory proxies generally locate on use. `@CacheLookup` stores the element and is unsafe for nodes that a framework rerenders. A cached reference can become stale even though the screen looks unchanged. I reduce that risk with stable locators, explicit conditions, and evidence-rich failures.

How would you review this implementation?

I verify API authenticity, locator uniqueness, wait boundaries, encapsulation, and parallel safety. I also ask whether a simpler official Selenium pattern communicates the same intent.

Why should a page object hide WebElements?

Hiding WebElements keeps tests focused on behavior and limits DOM knowledge to one layer. It also lets the page object add synchronization and return domain values without changing every caller.

Should implicit and explicit waits be mixed?

Mixing them can produce confusing timeout behavior because element lookup time contributes to explicit wait polling. Use an explicit, documented synchronization strategy and keep implicit wait at zero or a consciously chosen minimal value.

How do you make a locator maintainable?

Start with a stable product contract such as an ID, accessible relationship, or dedicated test attribute. Keep it concise, ensure it is unique, and avoid indexes or styling classes that change during redesign.

What belongs in a UI automation failure report?

Include the assertion, stack trace, URL, screenshot, browser and driver details, and relevant logs. For parallel execution, attach artifacts to the exact test and use unique filenames.

Frequently Asked Questions

What is the key fact about selenium PageFactory and FindBy java?

`PageFactory.initElements` decorates eligible fields. A `@FindBy` field is normally assigned a proxy, and the lookup is performed when code interacts with it. This lazy behavior is convenient, but it does not make an element immune to DOM replacement or timing failures. The best answer also states its limitations and how synchronization remains explicit.

When would you use selenium PageFactory and FindBy java?

A page object should expose user intent such as `loginAs`, not every underlying element. Initialization belongs in the constructor, while navigation, synchronization, and state reading remain explicit methods. I would use it only when that convention makes intent clearer for the team.

What is the biggest reliability risk?

Without `@CacheLookup`, PageFactory proxies generally locate on use. `@CacheLookup` stores the element and is unsafe for nodes that a framework rerenders. A cached reference can become stale even though the screen looks unchanged. I reduce that risk with stable locators, explicit conditions, and evidence-rich failures.

How would you review this implementation?

I verify API authenticity, locator uniqueness, wait boundaries, encapsulation, and parallel safety. I also ask whether a simpler official Selenium pattern communicates the same intent.

Why should a page object hide WebElements?

Hiding WebElements keeps tests focused on behavior and limits DOM knowledge to one layer. It also lets the page object add synchronization and return domain values without changing every caller.

Should implicit and explicit waits be mixed?

Mixing them can produce confusing timeout behavior because element lookup time contributes to explicit wait polling. Use an explicit, documented synchronization strategy and keep implicit wait at zero or a consciously chosen minimal value.

Related Guides