Skip to main content
SeleniumDecoded

Debugging Tips

Essential techniques for debugging Selenium tests, identifying failures, and fixing flaky tests.

Selenium 3 & 4 Stable

Debugging Selenium tests can be challenging. This guide covers practical techniques to identify and fix common issues.

Common Issues and Solutions

1. Element Not Found

Debugging Element Not Found
Selenium 3 & 4 Stable
// Problem: NoSuchElementException
// Step 1: Check if element exists in current context
// Are you in the right frame?
driver.switchTo().defaultContent();
// Step 2: Wait for element to be present
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
try {
WebElement element = wait.until(
ExpectedConditions.presenceOfElementLocated(By.id("myElement"))
);
} catch (TimeoutException e) {
// Element truly doesn't exist - check your locator
System.out.println("Current URL: " + driver.getCurrentUrl());
System.out.println("Page source contains element: " +
driver.getPageSource().contains("myElement"));
}
// Step 3: Verify locator in browser console
// Open DevTools and run:
// document.querySelector('#myElement')
// $x("//your/xpath")
# Problem: NoSuchElementException
# Step 1: Check if element exists in current context
# Are you in the right frame?
driver.switch_to.default_content()
# Step 2: Wait for element to be present
wait = WebDriverWait(driver, 10)
try:
element = wait.until(
EC.presence_of_element_located((By.ID, "myElement"))
)
except TimeoutException:
# Element truly doesn't exist - check your locator
print(f"Current URL: {driver.current_url}")
print(f"Page source contains element: {'myElement' in driver.page_source}")
# Step 3: Verify locator in browser console
# Open DevTools and run:
# document.querySelector('#myElement')
# $x("//your/xpath")
// Problem: NoSuchElementError
// Step 1: Check if element exists in current context
await driver.switchTo().defaultContent();
// Step 2: Wait for element to be present
try {
const element = await driver.wait(
until.elementLocated(By.id('myElement')),
10000
);
} catch (e) {
// Element truly doesn't exist - check your locator
console.log('Current URL:', await driver.getCurrentUrl());
const source = await driver.getPageSource();
console.log('Page source contains element:', source.includes('myElement'));
}
// Problem: NoSuchElementException
// Step 1: Check if element exists in current context
driver.SwitchTo().DefaultContent();
// Step 2: Wait for element to be present
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
try
{
IWebElement element = wait.Until(
ExpectedConditions.ElementExists(By.Id("myElement"))
);
}
catch (WebDriverTimeoutException)
{
// Element truly doesn't exist - check your locator
Console.WriteLine($"Current URL: {driver.Url}");
Console.WriteLine($"Page contains element: {driver.PageSource.Contains("myElement")}");
}

2. Element Not Clickable

Debugging Click Issues
Selenium 3 & 4 Stable
// Problem: ElementClickInterceptedException or Element not clickable
WebElement element = driver.findElement(By.id("submit"));
// Check 1: Is element visible?
System.out.println("Displayed: " + element.isDisplayed());
System.out.println("Enabled: " + element.isEnabled());
// Check 2: What's blocking it?
// In browser console: document.elementFromPoint(x, y)
// Solution 1: Wait for element to be clickable
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));
element.click();
// Solution 2: Scroll element into view
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView({block: 'center'})", element);
element.click();
// Solution 3: Wait for overlay to disappear
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("loading-overlay")));
element.click();
// Solution 4: JavaScript click (last resort)
js.executeScript("arguments[0].click()", element);
# Problem: ElementClickInterceptedException or Element not clickable
element = driver.find_element(By.ID, "submit")
# Check 1: Is element visible?
print(f"Displayed: {element.is_displayed()}")
print(f"Enabled: {element.is_enabled()}")
# Solution 1: Wait for element to be clickable
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
element.click()
# Solution 2: Scroll element into view
driver.execute_script("arguments[0].scrollIntoView({block: 'center'})", element)
element.click()
# Solution 3: Wait for overlay to disappear
wait.until(EC.invisibility_of_element_located((By.CLASS_NAME, "loading-overlay")))
element.click()
# Solution 4: JavaScript click (last resort)
driver.execute_script("arguments[0].click()", element)
// Problem: ElementClickInterceptedError
const element = await driver.findElement(By.id('submit'));
// Check 1: Is element visible?
console.log('Displayed:', await element.isDisplayed());
console.log('Enabled:', await element.isEnabled());
// Solution 1: Wait for element to be clickable
await driver.wait(until.elementIsVisible(element), 10000);
await driver.wait(until.elementIsEnabled(element), 10000);
await element.click();
// Solution 2: Scroll element into view
await driver.executeScript("arguments[0].scrollIntoView({block: 'center'})", element);
await element.click();
// Solution 3: JavaScript click (last resort)
await driver.executeScript('arguments[0].click()', element);
// Problem: ElementClickInterceptedException
IWebElement element = driver.FindElement(By.Id("submit"));
// Check 1: Is element visible?
Console.WriteLine($"Displayed: {element.Displayed}");
Console.WriteLine($"Enabled: {element.Enabled}");
// Solution 1: Wait for element to be clickable
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
element = wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("submit")));
element.Click();
// Solution 2: Scroll element into view
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].scrollIntoView({block: 'center'})", element);
element.Click();
// Solution 3: JavaScript click (last resort)
js.ExecuteScript("arguments[0].click()", element);

3. Stale Element Reference

Handling Stale Elements
Selenium 3 & 4 Stable
// Problem: StaleElementReferenceException
// Element was found but DOM changed before interaction
// Solution 1: Re-find the element
WebElement element = driver.findElement(By.id("dynamic"));
// ... page updates ...
try {
element.click();
} catch (StaleElementReferenceException e) {
element = driver.findElement(By.id("dynamic")); // Re-find
element.click();
}
// Solution 2: Wait for staleness then find again
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement oldElement = driver.findElement(By.id("dynamic"));
// Trigger page update
driver.findElement(By.id("refresh")).click();
// Wait for old element to become stale
wait.until(ExpectedConditions.stalenessOf(oldElement));
// Find new element
WebElement newElement = wait.until(
ExpectedConditions.presenceOfElementLocated(By.id("dynamic"))
);
// Solution 3: Retry pattern
public WebElement retryingFind(By locator) {
int attempts = 0;
while (attempts < 3) {
try {
return driver.findElement(locator);
} catch (StaleElementReferenceException e) {
attempts++;
}
}
throw new RuntimeException("Element still stale after 3 attempts");
}
# Problem: StaleElementReferenceException
# Element was found but DOM changed before interaction
from selenium.common.exceptions import StaleElementReferenceException
# Solution 1: Re-find the element
element = driver.find_element(By.ID, "dynamic")
# ... page updates ...
try:
element.click()
except StaleElementReferenceException:
element = driver.find_element(By.ID, "dynamic") # Re-find
element.click()
# Solution 2: Wait for staleness then find again
wait = WebDriverWait(driver, 10)
old_element = driver.find_element(By.ID, "dynamic")
# Trigger page update
driver.find_element(By.ID, "refresh").click()
# Wait for old element to become stale
wait.until(EC.staleness_of(old_element))
# Find new element
new_element = wait.until(EC.presence_of_element_located((By.ID, "dynamic")))
# Solution 3: Retry pattern
def retrying_find(driver, locator, attempts=3):
for _ in range(attempts):
try:
return driver.find_element(*locator)
except StaleElementReferenceException:
pass
raise Exception("Element still stale after retries")
// Problem: StaleElementReferenceError
// Solution 1: Re-find the element
let element = await driver.findElement(By.id('dynamic'));
try {
await element.click();
} catch (e) {
if (e.name === 'StaleElementReferenceError') {
element = await driver.findElement(By.id('dynamic'));
await element.click();
}
}
// Solution 2: Wait for staleness then find again
const oldElement = await driver.findElement(By.id('dynamic'));
await driver.findElement(By.id('refresh')).click();
await driver.wait(until.stalenessOf(oldElement), 10000);
const newElement = await driver.findElement(By.id('dynamic'));
// Solution 3: Retry pattern
async function retryingFind(driver, locator, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await driver.findElement(locator);
} catch (e) {
if (e.name !== 'StaleElementReferenceError') throw e;
}
}
throw new Error('Element still stale after retries');
}
// Problem: StaleElementReferenceException
// Solution 1: Re-find the element
IWebElement element = driver.FindElement(By.Id("dynamic"));
try
{
element.Click();
}
catch (StaleElementReferenceException)
{
element = driver.FindElement(By.Id("dynamic"));
element.Click();
}
// Solution 2: Wait for staleness then find again
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement oldElement = driver.FindElement(By.Id("dynamic"));
driver.FindElement(By.Id("refresh")).Click();
wait.Until(ExpectedConditions.StalenessOf(oldElement));
IWebElement newElement = wait.Until(
ExpectedConditions.ElementExists(By.Id("dynamic"))
);
// Solution 3: Retry pattern
public IWebElement RetryingFind(By locator, int attempts = 3)
{
for (int i = 0; i < attempts; i++)
{
try { return driver.FindElement(locator); }
catch (StaleElementReferenceException) { }
}
throw new Exception("Element still stale after retries");
}

Debugging Tools

Browser DevTools

// In browser console:
// Find element by CSS selector
document.querySelector('#myId')
document.querySelectorAll('.myClass')
// Find element by XPath
$x("//button[@id='submit']")
$x("//div[contains(text(), 'Hello')]")
// Check if element is visible
const el = document.querySelector('#myId');
const style = getComputedStyle(el);
console.log('display:', style.display);
console.log('visibility:', style.visibility);
console.log('opacity:', style.opacity);
// Find what's at specific coordinates
document.elementFromPoint(100, 200)
// Monitor events on an element
monitorEvents(document.querySelector('#myId'), 'click')

Taking Screenshots

Screenshot on Failure
Selenium 3 & 4 Stable
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import java.io.File;
import java.nio.file.Files;
public void takeScreenshot(String filename) {
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
try {
Files.copy(screenshot.toPath(),
new File("screenshots/" + filename + ".png").toPath());
} catch (IOException e) {
e.printStackTrace();
}
}
// In test teardown
@AfterMethod
public void afterMethod(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
takeScreenshot(result.getName());
}
}
import os
from datetime import datetime
def take_screenshot(driver, name):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"screenshots/{name}_{timestamp}.png"
os.makedirs("screenshots", exist_ok=True)
driver.save_screenshot(filename)
return filename
# Using pytest fixture
@pytest.fixture(autouse=True)
def screenshot_on_failure(request, driver):
yield
if request.node.rep_call.failed:
take_screenshot(driver, request.node.name)
async function takeScreenshot(driver, name) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `screenshots/${name}_${timestamp}.png`;
const fs = require('fs');
if (!fs.existsSync('screenshots')) {
fs.mkdirSync('screenshots');
}
const image = await driver.takeScreenshot();
fs.writeFileSync(filename, image, 'base64');
return filename;
}
public void TakeScreenshot(string name)
{
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string filename = $"screenshots/{name}_{timestamp}.png";
Directory.CreateDirectory("screenshots");
Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();
screenshot.SaveAsFile(filename);
}
// In test teardown
[TearDown]
public void TearDown()
{
if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed)
{
TakeScreenshot(TestContext.CurrentContext.Test.Name);
}
}

Debugging Checklist

CheckQuestion
URLAm I on the right page?
FrameAm I in the right frame/iframe?
TimingDid I wait long enough?
LocatorDoes my locator match in DevTools?
VisibilityIs the element visible/enabled?
OverlayIs something blocking the element?
StateDid the page change since I found the element?

Best Practices

  1. Add logging to track test execution flow
  2. Take screenshots on failure automatically
  3. Use explicit waits instead of sleep
  4. Verify locators in browser DevTools first
  5. Check for frames when elements aren’t found
  6. Review page state before and after actions

Next Steps