What if your tests could find buttons even when their names change a little?
Why XPath with contains and starts-with in Selenium Python? - Purpose & Use Cases
Imagine you have a huge webpage with many buttons and links. You want to click a button, but its exact name changes often, like 'Submit Form 1', 'Submit Form 2', and so on. Manually searching for the exact button each time is like finding a needle in a haystack.
Manually writing exact names or full paths for each element is slow and breaks easily when the page changes. You might miss some buttons or click the wrong one, causing errors and frustration.
Using XPath with contains and starts-with lets you find elements by parts of their names or attributes. This means your tests keep working even if the full text changes, making your automation smarter and more reliable.
driver.find_element(By.XPATH, "//button[text()='Submit Form 1']")driver.find_element(By.XPATH, "//button[contains(text(), 'Submit Form')]")This lets you write flexible tests that adapt to small changes in the webpage without breaking.
When testing a shopping site, product names might change slightly. Using contains helps you find the 'Add to Cart' button even if the product name updates.
Manual exact matching is fragile and slow.
contains and starts-with make element finding flexible.
Tests become more reliable and easier to maintain.
Practice
id attribute contains the text "submit" anywhere inside it?Solution
Step 1: Understand the contains() function
The contains() function checks if an attribute or text includes a specific substring anywhere inside it.Step 2: Apply contains() to the id attribute
Using contains(@id, 'submit') finds elements where the id attribute has 'submit' anywhere in its value.Final Answer:
contains(@id, 'submit') -> Option BQuick Check:
contains() = substring anywhere [OK]
- Using starts-with() when substring is not at start
- Using ends-with() which is not supported in XPath 1.0
- Using equals() which requires exact match
class attribute starts with "btn-"?Solution
Step 1: Identify the correct function for 'starts with'
The starts-with() function is used to check if an attribute value begins with a specific substring.Step 2: Check XPath syntax
The correct syntax is //element[starts-with(@class, 'btn-')]. Options C and D use invalid XPath syntax for this purpose.Final Answer:
//element[starts-with(@class, 'btn-')] -> Option CQuick Check:
starts-with() = prefix match [OK]
- Using contains() instead of starts-with() for prefix
- Using CSS selector syntax like ^= or *= in XPath
- Missing parentheses in function call
//div[contains(text(), 'Error') and starts-with(@class, 'alert-')]
Assuming the HTML contains:
<div class="alert-danger">Error: Invalid input</div> <div class="alert-success">Success</div> <div class="message-error">Error occurred</div>
Solution
Step 1: Analyze contains(text(), 'Error')
This matches div elements whose visible text includes 'Error'. The first and third divs contain 'Error'.Step 2: Analyze starts-with(@class, 'alert-')
This matches div elements whose class attribute starts with 'alert-'. The first and second divs match this.Step 3: Combine both conditions with AND
Only the first div satisfies both: text contains 'Error' and class starts with 'alert-'.Final Answer:
Selects only the div with class 'alert-danger' -> Option AQuick Check:
AND filters to first div only [OK]
- Assuming contains() matches attribute instead of text
- Ignoring the starts-with() condition
- Selecting all divs with 'Error' ignoring class prefix
//button[contains(@id, 'save-')]
But it also matches buttons with id "disable-save". How to fix it?
Solution
Step 1: Understand why contains() matches unwanted ids
contains(@id, 'save-') matches any id containing 'save-' anywhere, including 'disable-save'.Step 2: Use starts-with() to match only ids beginning with 'save-'
starts-with(@id, 'save-') ensures only ids starting exactly with 'save-' are matched.Final Answer:
//button[starts-with(@id, 'save-')] -> Option AQuick Check:
starts-with() fixes unwanted matches [OK]
- Using contains() when prefix match is needed
- Using ends-with() which XPath 1.0 does not support
- Matching text() instead of attribute
<a> elements where the href attribute starts with "https://" and the link text contains "Learn". Which XPath expression correctly does this?Solution
Step 1: Match href attribute starting with 'https://'
Use starts-with(@href, 'https://') to ensure href begins exactly with 'https://'.Step 2: Match link text containing 'Learn'
Use contains(text(), 'Learn') to find links whose visible text includes 'Learn' anywhere.Step 3: Combine both conditions with AND
Both conditions must be true, so use and between them.Final Answer:
//a[starts-with(@href, 'https://') and contains(text(), 'Learn')] -> Option DQuick Check:
starts-with() + contains() combined correctly [OK]
- Using contains() for href prefix instead of starts-with()
- Swapping text() and attribute in functions
- Using starts-with() on text when contains() is needed
Ready to prove it?
Pass the test and this pattern moves unknown
