πŸ’‘ Share CareerRaah β€” it's 100% free! πŸš€

Back to Home Dashboard| Selenium Scenario Hub 2026

Top 100 Selenium Interview Questions

Real-world, scenario-based Q&A featuring Selenium 4 + Java code snippets, synchronization patterns, stale elements, and headless CI/CD gotchas.

100 QuestionsCode SnippetsBeginner β†’ AdvancedFree
Progress0/100
0%
01.

Dynamic Locator Keeps Changing on Refresh

IntermediateLocators

Dynamic elements are extremely common in modern frameworks (React, Angular, Vue) where class names or IDs are auto-generated on load (e.g., id="btn-submit_9a7c3"). A professional automation engineer identifies the root cause and bypasses these dynamic properties by leveraging stable custom attributes, utilizing relative XPath axes, or using text-matching selectors rather than brittle auto-generated values.

Key Takeaways & Core Strategy

  • βœ“Avoid dynamic attributes (like auto-generated IDs or class names)
  • βœ“Identify a stable custom data-attribute (e.g., data-testid, data-qa)
  • βœ“Build smart Relative XPath using contains(), starts-with() or text()
  • βœ“Utilize relative parent-child-sibling relationships in DOM tree
  • βœ“Collaborate with developers to add stable hooks for testing

⚠️ Senior Engineering Warning

Never hardcode dynamic IDs (like btn_4920a) or rely on absolute XPath paths starting from the html root. They will break your test suite on every backend deployment or slight DOM modification.

Deep Dive Explanation

If no stable attributes exist, always inspect the DOM for surrounding static elements. Connect to them first as an anchor, and navigate to the target element using axes like following-sibling, parent, or descendant.

code snippet
// ❌ brittle dynamic ID: driver.findElement(By.id("btn-submit_9a7c3"));

// βœ… Best practice: Locate using custom data-attributes
WebElement submitBtn = driver.findElement(By.xpath("//button[@data-testid='submit-login']"));

// βœ… Sibling Strategy: Locate an input field based on its stable text label
WebElement emailField = driver.findElement(By.xpath("//label[text()='Email']/following-sibling::input"));

// βœ… Match Partial Dynamic Properties using XPath functions
WebElement partialBtn = driver.findElement(By.xpath("//input[contains(@id, 'login-btn_')]"));
View Page
02.

Locating Elements with No ID, Name, or Stable XPath

IntermediateLocators

When standard attributes like ID or Name are absent, you must look for accessibility elements or positional relationships. Selenium 4 introduces Relative Locators, allowing you to find elements based on their spatial orientation to other stable, known elements. Additionally, you can utilize text-based XPath queries or narrow down search context by first locating a stable container parent.

Key Takeaways & Core Strategy

  • βœ“Leverage accessibility attributes (aria-label, placeholder, title)
  • βœ“Employ Selenium 4 Relative Locators (above, below, toLeftOf, toRightOf, near)
  • βœ“Construct robust text-based XPath matching with normalize-space()
  • βœ“Navigate relative DOM hierarchy using stable parent containers

⚠️ Senior Engineering Warning

If your XPath is highly complex (e.g., with more than 3-4 nested descendant levels), it is a major warning sign. It makes your tests fragile and hard to maintain.

Deep Dive Explanation

Relative locators are excellent for forms and grids. Always make sure to combine them with standard explicit waits to guarantee the reference element is visible before locating the target.

code snippet
import static org.openqa.selenium.support.locators.RelativeLocator.*;

// βœ… Locate stable reference point
WebElement loginHeader = driver.findElement(By.xpath("//h2[text()='Login']"));

// βœ… Selenium 4 Relative Locators: Find tag near stable element
WebElement usernameField = driver.findElement(with(By.tagName("input")).below(loginHeader));

// βœ… Locate relative to stable sibling
WebElement submitButton = driver.findElement(with(By.tagName("button")).below(usernameField));

// βœ… XPath Text matching with space normalization
WebElement welcomeMsg = driver.findElement(By.xpath("//div[normalize-space()='Welcome back, Guest']"));
View Page
03.

Element is Not Clickable at Point Error

IntermediateExceptions

The "Element is not clickable at point" error occurs when a dynamic overlay (like a loading spinner, cookie consent banner, or sticky header) blocks the element, or it is off-screen. To resolve this, you must explicitly wait for the blocking overlay to become invisible, scroll the element into view, or use JavaScript Click only when the blockage is a known, non-actionable overlay.

Key Takeaways & Core Strategy

  • βœ“Understand ElementClickInterceptedException causes (overlays, loading spinners)
  • βœ“Apply Explicit Wait for elementToBeClickable to clear loaders
  • βœ“Scroll the element into the viewport center using JavaScript Executor
  • βœ“Use JavaScript Executor click as a controlled fallback strategy

⚠️ Senior Engineering Warning

Using JavascriptExecutor to click elements as a default fix is an anti-pattern. JS click bypasses browser safety restrictions, meaning it will click hidden, disabled, or covered elements, failing to test the actual user experience.

Deep Dive Explanation

Always debug this by taking a screenshot on failure. If a loader or modal is visible in the screenshot, you need to add an explicit wait for that spinner to disappear before clicking.

code snippet
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

// βœ… Best Practice: Wait for overlapping spinner to disappear first
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-spinner")));

// βœ… Explicit Wait for element to become clickable
WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("btn-submit")));

// βœ… Scroll to element prior to click (fixes sticky header overlap)
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView({block: 'center'});", button);
button.click();

// βœ… Fallback Only: Perform direct JavaScript click
((JavascriptExecutor) driver).executeScript("arguments[0].click();", button);
View Page
04.

Handling Stale Element Reference Exception

AdvancedExceptions

A StaleElementReferenceException is thrown when a previously located element is no longer attached to the page DOM. This happens when the page refreshes, an AJAX request replaces a container, or a framework like React tears down and recreates elements. Because the reference ID held by the driver is now invalid, you must re-query the DOM to fetch the new, valid element reference.

Key Takeaways & Core Strategy

  • βœ“Identify causes (page refresh, AJAX container update, DOM replacement)
  • βœ“Never store active WebElement references across page transitions
  • βœ“Implement a robust try-catch retry mechanism to re-locate the element
  • βœ“Use WebDriverWait with ExpectedConditions.refreshed() to auto-recover

⚠️ Senior Engineering Warning

Avoid using @CacheLookup in Selenium Page Factory for elements that refresh dynamically. Caching references causes StaleElementReferenceException the moment the element is detached and rebuilt.

Deep Dive Explanation

Always design your Page Objects to re-fetch elements dynamically within action methods instead of storing them as class variables. This naturally prevents stale references.

code snippet
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;

// βœ… Solution 1: Use WebDriverWait.refreshed to auto-locate on staleness
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.refreshed(
    ExpectedConditions.elementToBeClickable(By.id("save-button"))
)).click();

// βœ… Solution 2: Implement a clean retry loop for dynamic tables
public void clickDynamicElement(By locator, int maxAttempts) {
    int attempts = 0;
    while (attempts < maxAttempts) {
        try {
            driver.findElement(locator).click();
            return;
        } catch (StaleElementReferenceException e) {
            attempts++;
        }
    }
    throw new StaleElementReferenceException("Failed to click element after " + maxAttempts + " retries.");
}
View Page
βš”οΈ
Test Your WebDriver Skills: Ready to prove your automation mastery?
Start Selenium Quiz
05.

Random Popups and Dynamic Ad Interruption

AdvancedSynchronization

Random popups (like promotional offers, newsletters, or GDPR cookie compliance forms) can appear unexpectedly and block the main UI thread. A professional SDET manages this by configuring the browser driver options to disable notifications, utilizing quick conditional checks with `driver.findElements()` (which does not throw exceptions if empty), or using low-timeout try-catch blocks.

Key Takeaways & Core Strategy

  • βœ“Disable popups, notifications, and ads via browser profile settings
  • βœ“Check for popup presence safely using driver.findElements() without delays
  • βœ“Utilize try-catch blocks with low timeouts to handle optional modals
  • βœ“Implement a teardown/setup hook in TestNG/JUnit to dismiss overlays

⚠️ Senior Engineering Warning

Never put a standard explicit wait (like 10 seconds) on a random popup. If the popup does not appear, your tests will waste 10 seconds waiting, adding massive, unnecessary latency to your test suite.

Deep Dive Explanation

Using findElements() is the fastest, cleanest way to handle optional elements because it does not trigger the implicit wait timeout when looking for an element that might not exist.

code snippet
import org.openqa.selenium.chrome.ChromeOptions;
import java.util.List;

// βœ… Configuration Strategy: Disable ads & popups at browser start
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-popup-blocking");
options.addArguments("--disable-notifications");

// βœ… Runtime Check: Handle popup instantly without throwing errors
public void dismissCookieBanner() {
    // findElements returns empty list immediately if not present, avoiding 10s wait
    List<WebElement> banners = driver.findElements(By.cssSelector("#gdpr-cookie-consent"));
    if (!banners.isEmpty() && banners.get(0).isDisplayed()) {
        banners.get(0).click();
        System.out.println("GDPR banner dismissed.");
    }
}

// βœ… Optional Modal Strategy: Fast-fail wait
public void closeNewsletterModal() {
    try {
        // Wait only 2 seconds for optional popup
        new WebDriverWait(driver, Duration.ofSeconds(2))
            .until(ExpectedConditions.elementToBeClickable(By.id("close-newsletter")))
            .click();
    } catch (TimeoutException e) {
        // Modal did not show up, proceed without failing
    }
}
View Page
06.

Test Passes Locally but Fails in Headless CI/CD

AdvancedCI/CD

CI/CD servers are usually headless (no GUI) and operate on shared virtualized hardware with lower resource allocations. These differences often lead to timing inconsistencies, responsive layouts breaking (hiding desktop menus), or dynamic components failing to load in time. To fix this, always set explicit viewport arguments, ensure environment versions align, and capture screen states on failures.

Key Takeaways & Core Strategy

  • βœ“Configure explicit window-size arguments to match desktop resolutions
  • βœ“Align local browser version with CI/CD runner browser binary version
  • βœ“Increase explicit timeouts slightly in CI to account for resource limits
  • βœ“Implement automatic screenshot capturing on test failure listener

⚠️ Senior Engineering Warning

Do not rely on driver.manage().window().maximize() in headless CI pipelines. In virtual environments, maximize() often defaults to a very small, restricted layout (like 800x600), hiding responsive menus.

Deep Dive Explanation

Setting a fixed screen resolution like 1920x1080 is critical. Modern web pages are responsive, and if your headless browser defaults to a small size, elements will collapse into hamburger menus, breaking your desktop locators.

code snippet
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.chrome.ChromeDriver;

// βœ… Configure Headless options properly for CI pipeline
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new"); // Use modern headless engine
options.addArguments("--window-size=1920,1080"); // Force standard desktop layout
options.addArguments("--no-sandbox"); // Required for Linux container permission bypass
options.addArguments("--disable-dev-shm-usage"); // Prevents shared memory crashes in Docker
options.addArguments("--disable-gpu"); // Recommended for server execution

WebDriver driver = new ChromeDriver(options);
View Page
07.

Handling Extremely Slow Page Loads

IntermediateSynchronization

Selenium's default page load strategy blocks the test thread until the browser completely fetches and parses all subresources (images, third-party trackers, scripts). If a slow tracker hangs, the entire test blocks and fails with a page load timeout. You can optimize this by changing the Page Load Strategy to "eager" (which proceeds once the HTML DOM is interactive) or waiting for document.readyState via Javascript.

Key Takeaways & Core Strategy

  • βœ“Configure custom pageLoadTimeout values on the driver object
  • βœ“Utilize EAGER page load strategy to ignore slow trackers and styling
  • βœ“Implement programmatical Javascript waits for document.readyState
  • βœ“Track load times and capture network HAR logs for bottleneck analysis

⚠️ Senior Engineering Warning

Avoid inflating your pageLoadTimeout limit (e.g. to 120 seconds) to bypass slow loading. This masks real performance issues in your application. Instead, switch to eager loading or consult the development team.

Deep Dive Explanation

PageLoadStrategy.EAGER is a game changer for sites with slow ads or analytics trackers. It allows your tests to run the moment the functional HTML layout is ready.

code snippet
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.chrome.ChromeOptions;

// βœ… Set Page Load Strategy to EAGER (Stops waiting for images/trackers)
ChromeOptions options = new ChromeOptions();
options.setPageLoadStrategy(PageLoadStrategy.EAGER);
WebDriver driver = new ChromeDriver(options);

// βœ… Configure explicit page load timeout limit (e.g., 20 seconds)
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(20));

// βœ… Wait programmatically for Javascript document load completion
public void waitForPageToLoad() {
    new WebDriverWait(driver, Duration.ofSeconds(15)).until(
        d -> ((JavascriptExecutor) d)
            .executeScript("return document.readyState").equals("complete")
    );
}
View Page
08.

Selecting Dynamically Loaded AJAX Dropdown Options

IntermediateSynchronization

Modern web applications use custom styling tags (like div, ul, li) to render dropdowns, fetching data dynamically via AJAX only after the user clicks the field. Standard Select commands do not work here. You must first click the container to trigger the API, explicitly wait for option elements to be visible, and click the option matching your text.

Key Takeaways & Core Strategy

  • βœ“Trigger dropdown options load by clicking the wrapper first
  • βœ“Avoid Selenium Select class on custom React/Angular divs or lists
  • βœ“Use visibilityOfAllElementsLocatedBy to wait for dynamic elements
  • βœ“Iterate option lists dynamically to click matching target text value

⚠️ Senior Engineering Warning

Never use the Select helper class on custom divs or ul/li list containers. The Select class only works with standard HTML <select> tags, throwing an UnexpectedTagNameException if applied elsewhere.

Deep Dive Explanation

Always wait for the visibility of the options list, not just presence in DOM. If you attempt to click an option that is present but hidden, Selenium will throw an ElementNotInteractableException.

code snippet
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.util.List;

public void selectDynamicAjaxOption(By dropdownHost, By optionLocator, String targetText) {
    // 1. Click dropdown to open and trigger AJAX network request
    driver.findElement(dropdownHost).click();

    // 2. Wait explicitly until dropdown options list becomes visible
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    List<WebElement> options = wait.until(
        ExpectedConditions.visibilityOfAllElementsLocatedBy(optionLocator)
    );

    // 3. Dynamic selection loop
    for (WebElement option : options) {
        if (option.getText().trim().equalsIgnoreCase(targetText)) {
            option.click();
            return;
        }
    }
    throw new NoSuchElementException("Failed to find dynamic option: " + targetText);
}
View Page
09.

Flakiness Caused by Network Latency and API Delays

AdvancedSynchronization

Slow backend services or network delay will cause automation scripts to fail if they look for elements before they exist. Using static Thread.sleep() delays is a poor solution that increases execution times. Implementing dynamic Explicit and Fluent waits allows the framework to poll the DOM frequently, immediately resuming as soon as the element is ready.

Key Takeaways & Core Strategy

  • βœ“Abolish static Thread.sleep() sleeps across the entire framework
  • βœ“Use WebDriverWait to apply non-blocking waits for specific conditions
  • βœ“Implement FluentWait to ignore exceptions and customize polling rates
  • βœ“Configure appropriate global implicit timeouts with caution

⚠️ Senior Engineering Warning

Mixing implicit and explicit waits in the same framework is strongly discouraged by the Selenium team. Doing so causes unpredictable wait durations, sometimes turning a 10-second timeout into a 90-second delay.

Deep Dive Explanation

Explicit waits are active, non-blocking conditions. If an API responds in 50 milliseconds, the test proceeds instantly, ensuring maximum suite speed compared to hardcoded sleeps.

code snippet
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import java.util.NoSuchElementException;

// βœ… Build a customized Fluent Wait ignoring specific exceptions
Wait<WebDriver> fluentWait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(15))
    .pollingEvery(Duration.ofMillis(500)) // Poll DOM every 500ms
    .ignoring(NoSuchElementException.class)
    .ignoring(StaleElementReferenceException.class);

// βœ… Dynamic condition: Wait until element is loaded and contains non-empty text
WebElement dynamicValue = fluentWait.until(d -> {
    WebElement el = d.findElement(By.id("dashboard-metrics"));
    String val = el.getText();
    return (!val.isEmpty() && !val.equals("Loading...")) ? el : null;
});
View Page
10.

Interacting with encapsulated Shadow DOM Elements

AdvancedAdvanced

Shadow DOM encapsulates web component structures, isolating them from the main DOM document tree. Standard locators and XPath cannot see past this boundary. In Selenium 4, you can call getShadowRoot() on the shadow host element to obtain its SearchContext. From there, you can query inner child elements directly using CSS Selectors.

Key Takeaways & Core Strategy

  • βœ“Access Shadow DOM elements via Selenium 4 getShadowRoot() API
  • βœ“Query inside shadow contexts strictly with CSS selectors (no XPath)
  • βœ“Use JavascriptExecutor script queries as a fallback compatibility method
  • βœ“Traverse multiple layers of nested shadow roots sequentially

⚠️ Senior Engineering Warning

Standard XPath expressions starting with // cannot pierce the Shadow DOM boundary. Trying to locate a shadow element with standard XPath will result in a NoSuchElementException every time.

Deep Dive Explanation

Always inspect the element in Chrome DevTools first. If you see "#shadow-root (open)", it means the element is encapsulated. Retrieve the parent "Shadow Host" element first, then use getShadowRoot() to find the internal target.

code snippet
import org.openqa.selenium.SearchContext;

// βœ… Selenium 4: Accessing Shadow DOM directly
WebElement shadowHost = driver.findElement(By.cssSelector("theme-settings-panel"));

// Get the encapsulated search context
SearchContext shadowContext = shadowHost.getShadowRoot();

// Locate internal element inside the shadow root (CSS selector ONLY, XPath not supported)
WebElement darkModeToggle = shadowContext.findElement(By.cssSelector("button#dark-mode-toggle"));
darkModeToggle.click();

// βœ… Fallback: Access Shadow DOM via Javascript Executor (highly compatible)
WebElement toggleViaJS = (WebElement) ((JavascriptExecutor) driver).executeScript(
    "return document.querySelector('theme-settings-panel').shadowRoot.querySelector('button#dark-mode-toggle')"
);
toggleViaJS.click();
View Page

Finished practicing?

Head back to the main lobby to explore more interview prep tracks and dashboard tools.

🏠 Back to Home Dashboard
🎭

Transitioning to Playwright?

Master ARIA locators, isolated browser contexts, storage state persistence, fixtures, and dynamic network interception.

Master Playwright