Absolute vs relative XPath in Selenium Python - Automation Approaches Compared
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # Setup WebDriver (assuming chromedriver is in PATH) driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) try: # Step 1: Open login page driver.get('https://example.com/login') # Step 2: Locate login button using absolute XPath absolute_xpath = '/html/body/div/main/form/button' login_button_abs = wait.until(EC.visibility_of_element_located((By.XPATH, absolute_xpath))) assert login_button_abs.is_displayed(), 'Login button not visible using absolute XPath' # Step 3: Locate login button using relative XPath relative_xpath = '//button[@id="loginBtn"]' login_button_rel = wait.until(EC.visibility_of_element_located((By.XPATH, relative_xpath))) assert login_button_rel.is_displayed(), 'Login button not visible using relative XPath' # Step 4: Click login button using relative XPath login_button_rel.click() # Step 5: Verify URL contains '/dashboard' wait.until(EC.url_contains('/dashboard')) assert '/dashboard' in driver.current_url, 'Did not navigate to dashboard after login' finally: driver.quit()
This script opens the login page using Selenium WebDriver.
It first finds the login button using an absolute XPath, which starts from the root of the HTML document. This is fragile but shows how absolute XPath looks.
Then it finds the same button using a relative XPath, which is shorter and more maintainable.
Explicit waits ensure the button is visible before interacting.
After clicking the button using the relative XPath, the script waits until the URL contains '/dashboard' to confirm navigation.
Assertions check that elements are visible and navigation is successful.
Finally, the browser closes to clean up.
Now add data-driven testing with 3 different login button IDs to verify locating buttons with different relative XPaths.
Practice
Solution
Step 1: Understand XPath types
Absolute XPath always starts from the root node, indicated by a single slash (/), and follows the full path to the target element.Step 2: Compare with relative XPath
Relative XPath starts from anywhere in the document, often using double slashes (//) and conditions to locate elements.Final Answer:
It starts from the root node and follows the full path to the element. -> Option AQuick Check:
Absolute XPath = full path from root [OK]
- Confusing absolute with relative XPath syntax
- Thinking relative XPath always starts at root
- Assuming absolute XPath uses conditions only
Solution
Step 1: Identify relative XPath syntax
Relative XPath uses double slashes (//) to search anywhere in the document for matching elements.Step 2: Check the options
//button[text()='Submit'] uses //button[text()='Submit'], which correctly finds a button element with exact text 'Submit'. /html/body/button[text()='Submit'] is absolute XPath. button[text()='Submit'] misses the // and is invalid XPath. //*[@id='submit'] uses an attribute selector but does not specify text.Final Answer:
//button[text()='Submit'] -> Option BQuick Check:
Relative XPath uses // and conditions [OK]
- Using single slash / for relative XPath
- Omitting // before element name
- Confusing attribute and text selectors
<div>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>What will the XPath
//ul/li[2] select?Solution
Step 1: Understand the XPath expression
The XPath //ul/li[2] selects the second- child element of any <ul> element anywhere in the document.
Step 2: Match with HTML structure
The <ul> has three- children: Home (1), About (2), Contact (3). So li[2] selects About.
Final Answer:
The second list item <li>About</li> -> Option AQuick Check:
li[2] = second child element [OK]
- Confusing index starting at 0 instead of 1
- Thinking //ul/li[2] selects second ul element
- Assuming XPath is zero-based
/html/body/div/button[@id='login']But your test fails to find the element after page update. What is the likely issue?
Solution
Step 1: Analyze the XPath type
The XPath starts with a single slash /, so it is absolute and depends on the full path from root.Step 2: Understand fragility of absolute XPath
If the page structure changes (like adding a div), the absolute path breaks and element is not found.Final Answer:
The XPath is absolute and fragile; page structure changed breaking the path. -> Option DQuick Check:
Absolute XPath breaks if page structure changes [OK]
- Blaming attribute syntax instead of XPath type
- Assuming XPath cannot find buttons
- Ignoring page structure changes
<div class='product'> <span class='name'>Product A</span> <span class='price'>$20</span> </div> <div class='product'> <span class='name'>Product B</span> <span class='price'>$30</span> </div>
Which XPath is best to find the name of the product priced $20?
Solution
Step 1: Understand the requirement
We want the product name where the price is exactly '$20'. So we must find a product div with a price span of '$20' and then get its name span.Step 2: Evaluate each XPath
//div[@class='product'][span[@class='price' and text()='$20']]//span[@class='name'] selects div with class 'product' having a span price '$20', then selects the name span inside it. This is precise and stable.
/html/body/div[1]/span[1] is absolute XPath and fragile.
//span[@class='price' and text()='$20']/preceding-sibling::span[@class='name'] tries to find price span then preceding sibling name span, which matches the HTML structure where name is before price.
//div[@class='product']/span[@class='name'] selects all product names, ignoring price.Final Answer:
//div[@class='product'][span[@class='price' and text()='$20']]//span[@class='name'] -> Option CQuick Check:
Use relative XPath with conditions for stable element [OK]
- Using absolute XPath that breaks easily
- Selecting elements without conditions
- Ignoring element hierarchy in XPath
Ready to prove it?
Pass the test and this pattern moves unknown
