Bird
Raised Fist0
Selenium Pythontesting~15 mins

XPath axes (parent, child, sibling) in Selenium Python - Build an Automation Script

Choose your learning style10 modes available
Verify navigation using XPath axes parent, child, and sibling
Preconditions (2)
Step 1: Open the sample webpage URL
Step 2: Locate the list item with text 'Item 2' using XPath child axis from the parent list
Step 3: From 'Item 2', navigate to its parent element and verify it is the list with id 'menu'
Step 4: From 'Item 2', locate its following sibling list item and verify its text is 'Item 3'
Step 5: From 'Item 2', locate its child sub-item with text 'Subitem 2.1' using XPath child axis
Step 6: Verify all located elements are displayed on the page
✅ Expected Result: The test should confirm that the XPath axes parent, child, and sibling correctly locate the elements and all elements are visible on the page
Automation Requirements - Selenium with Python
Assertions Needed:
Assert the parent element's id is 'menu'
Assert the following sibling's text is 'Item 3'
Assert the child sub-item's text is 'Subitem 2.1'
Assert all located elements are displayed
Best Practices:
Use explicit waits to wait for elements to be present and visible
Use By.XPATH with clear and maintainable XPath expressions
Avoid absolute XPath; use relative XPath with axes
Use Page Object Model pattern for element locators and actions
Automated Solution
Selenium Python
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

class MenuPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    def get_item_2(self):
        xpath = "//ul[@id='menu']/li[normalize-space(text())='Item 2']"
        return self.wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))

    def get_parent_of_item_2(self):
        # Using parent axis
        xpath = "//ul[@id='menu']/li[normalize-space(text())='Item 2']/parent::ul"
        return self.wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))

    def get_following_sibling_of_item_2(self):
        # Using following-sibling axis
        xpath = "//ul[@id='menu']/li[normalize-space(text())='Item 2']/following-sibling::li[1]"
        return self.wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))

    def get_child_subitem_of_item_2(self):
        # Using child axis
        xpath = "//ul[@id='menu']/li[normalize-space(text())='Item 2']/child::ul/li[normalize-space(text())='Subitem 2.1']"
        return self.wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))


def test_xpath_axes():
    driver = webdriver.Chrome()
    driver.get("https://example.com/sample-menu")  # Replace with actual URL

    menu_page = MenuPage(driver)

    item_2 = menu_page.get_item_2()
    assert item_2.is_displayed(), "Item 2 should be visible"

    parent = menu_page.get_parent_of_item_2()
    assert parent.get_attribute('id') == 'menu', f"Parent id should be 'menu', got {parent.get_attribute('id')}"

    sibling = menu_page.get_following_sibling_of_item_2()
    assert sibling.text.strip() == 'Item 3', f"Following sibling text should be 'Item 3', got {sibling.text.strip()}"

    child_subitem = menu_page.get_child_subitem_of_item_2()
    assert child_subitem.text.strip() == 'Subitem 2.1', f"Child subitem text should be 'Subitem 2.1', got {child_subitem.text.strip()}"
    assert child_subitem.is_displayed(), "Child subitem should be visible"

    driver.quit()

This script uses Selenium with Python to automate the test case for XPath axes.

The MenuPage class encapsulates element locators using XPath axes:

  • get_item_2: Locates 'Item 2' using a relative XPath child from the list with id 'menu'.
  • get_parent_of_item_2: Uses the parent:: axis to get the parent ul element of 'Item 2'.
  • get_following_sibling_of_item_2: Uses following-sibling:: axis to get the next sibling list item.
  • get_child_subitem_of_item_2: Uses child:: axis to get the nested sub-item 'Subitem 2.1'.

The test function test_xpath_axes opens the webpage, creates the page object, and performs assertions to verify:

  • Elements are visible
  • Parent element has correct id
  • Sibling and child elements have expected text

Explicit waits ensure elements are present and visible before interaction, improving test stability.

Common Mistakes - 3 Pitfalls
Using absolute XPath like /html/body/ul/li[2]
Not waiting for elements before accessing them
Using incorrect XPath axes syntax or mixing axes improperly
Bonus Challenge

Now add data-driven testing with 3 different list items: 'Item 1', 'Item 2', and 'Item 3', verifying their parent, sibling, and child elements accordingly.

Show Hint

Practice

(1/5)
1. Which XPath axis selects the direct parent of the current node?
easy
A. child::
B. parent::
C. following-sibling::
D. preceding-sibling::

Solution

  1. Step 1: Understand XPath axes

    XPath axes describe relationships between nodes, such as parent, child, or siblings.
  2. Step 2: Identify the axis for parent node

    The parent:: axis selects the direct parent of the current node.
  3. Final Answer:

    parent:: -> Option B
  4. Quick Check:

    Parent axis = parent:: [OK]
Hint: Parent axis always uses 'parent::' [OK]
Common Mistakes:
  • Confusing parent:: with child::
  • Using sibling axes to find parent
  • Forgetting axes syntax with double colons
2. Which of the following is the correct XPath syntax to select all child <li> elements of a <ul> element?
easy
A. //ul/parent::li
B. //ul/preceding-sibling::li
C. //ul/following-sibling::li
D. //ul/child::li

Solution

  1. Step 1: Understand child axis usage

    The child:: axis selects direct children of the current node.
  2. Step 2: Apply correct syntax for child li elements

    Using //ul/child::li selects all li children of ul.
  3. Final Answer:

    //ul/child::li -> Option D
  4. Quick Check:

    Child axis syntax = child:: [OK]
Hint: Use 'child::' to select direct children nodes [OK]
Common Mistakes:
  • Using parent:: instead of child::
  • Using sibling axes for children
  • Omitting the axis and expecting child selection
3. Given the following HTML snippet:
<div>
  <h2>Title</h2>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</div>

What does the XPath //h2/following-sibling::p[1] select?
medium
A. No element, XPath is invalid
B. The second p element inside the div
C. The first p element inside the div
D. The h2 element itself

Solution

  1. Step 1: Understand following-sibling axis

    The following-sibling::p[1] selects the first p sibling after the h2 node.
  2. Step 2: Apply to given HTML

    After h2, the first p is "Paragraph 1", so it selects that element.
  3. Final Answer:

    The first <p> element inside the <div> -> Option C
  4. Quick Check:

    following-sibling::p[1] = first p after h2 [OK]
Hint: following-sibling::p[1] picks first p after current node [OK]
Common Mistakes:
  • Selecting the second p instead of the first
  • Confusing preceding-sibling with following-sibling
  • Thinking it selects children instead of siblings
4. You wrote this XPath to select the previous sibling of a div element:
//div/preceding-sibling::div[1]
But it returns no elements. What is the most likely reason?
medium
A. The div has no preceding sibling div elements
B. The syntax is incorrect; axes cannot be used with //
C. You should use parent::div instead
D. preceding-sibling axis selects children, not siblings

Solution

  1. Step 1: Understand preceding-sibling axis

    The preceding-sibling::div[1] selects the immediate previous sibling div element.
  2. Step 2: Reason why no elements returned

    If no elements are returned, it means the current div has no preceding sibling div.
  3. Final Answer:

    The <div> has no preceding sibling <div> elements -> Option A
  4. Quick Check:

    preceding-sibling returns nothing if no previous siblings [OK]
Hint: No preceding sibling means empty result, not syntax error [OK]
Common Mistakes:
  • Thinking axes can't be used with //
  • Confusing parent:: with preceding-sibling::
  • Assuming preceding-sibling selects children
5. You want to select all span elements that are children of a div whose immediate parent is a section. Which XPath expression correctly uses axes to achieve this?
hard
A. //section/child::div/child::span
B. //div/parent::section/child::span
C. //section/parent::div/child::span
D. //span/parent::div/parent::section

Solution

  1. Step 1: Understand the hierarchy

    The span elements are children of div, and that div is a child of section.
  2. Step 2: Build XPath with axes

    //section/child::div/child::span selects span children of div children of section.
  3. Step 3: Check other options

    //div/parent::section/child::span selects span children of section, which is incorrect. //section/parent::div/child::span and D misuse axes or order.
  4. Final Answer:

    //section/child::div/child::span -> Option A
  5. Quick Check:

    Use child axes from section to div to span [OK]
Hint: Chain child:: axes from parent to target child [OK]
Common Mistakes:
  • Using parent:: in wrong direction
  • Selecting wrong node levels
  • Mixing sibling axes instead of child axes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard