Bird
Raised Fist0
Selenium Javatesting~15 mins

XPath functions (contains, starts-with) in Selenium Java - Deep Dive

Choose your learning style10 modes available
Overview - XPath functions (contains, starts-with)
What is it?
XPath functions like contains() and starts-with() help find elements on a web page by matching parts of their attributes or text. They let you search for elements even if you don't know the full exact value. This makes locating elements more flexible and powerful in automated tests.
Why it matters
Without these functions, tests would break easily if element attributes change slightly or have dynamic parts. Using contains() and starts-with() makes tests more stable and less fragile, saving time and reducing errors in automation. It helps testers handle real-world web pages that often change or have complex structures.
Where it fits
Before learning these functions, you should understand basic XPath syntax and how to locate elements by exact attribute values. After mastering these functions, you can learn other XPath functions like text(), normalize-space(), and advanced selectors to write even more robust tests.
Mental Model
Core Idea
XPath functions contains() and starts-with() let you find elements by matching partial attribute or text values, making element selection flexible and resilient.
Think of it like...
It's like searching for a book in a library by remembering part of its title or the first few words, instead of the full exact title.
XPath Expression Examples:

┌───────────────────────────────┐
│ //tag[contains(@attr, 'value')] │  ← finds elements where 'attr' includes 'value'
├───────────────────────────────┤
│ //tag[starts-with(@attr, 'start')] │  ← finds elements where 'attr' starts with 'start'
└───────────────────────────────┘
Build-Up - 7 Steps
1
FoundationBasic XPath Attribute Matching
🤔
Concept: Learn how XPath selects elements by exact attribute values.
XPath lets you find elements by matching attributes exactly. For example, //input[@id='username'] finds an input element with id exactly 'username'. This is simple but can fail if the attribute value changes slightly.
Result
You can locate elements with exact attribute matches.
Understanding exact matching is the base for knowing why partial matching functions like contains() are needed.
2
FoundationXPath Syntax for Functions
🤔
Concept: Understand how to use functions inside XPath expressions.
XPath functions are used inside square brackets to filter elements. For example, //div[contains(text(), 'hello')] finds divs whose text includes 'hello'. Functions take arguments and return true or false to select elements.
Result
You can write XPath expressions using functions to filter elements.
Knowing the syntax of functions inside XPath is essential before using specific functions like contains() or starts-with().
3
IntermediateUsing contains() for Partial Matching
🤔Before reading on: do you think contains() matches only the start of a string or any part? Commit to your answer.
Concept: contains() checks if an attribute or text contains a given substring anywhere inside it.
Example: //a[contains(@href, 'login')] finds links whose href attribute includes 'login' anywhere, like 'user-login.html' or 'loginPage'. This helps when attribute values have dynamic parts.
Result
You can locate elements even if you know only part of an attribute or text value.
Understanding contains() helps write flexible selectors that survive small changes in web pages.
4
IntermediateUsing starts-with() for Prefix Matching
🤔Before reading on: does starts-with() match anywhere in the string or only at the beginning? Commit to your answer.
Concept: starts-with() checks if an attribute or text starts exactly with a given substring.
Example: //input[starts-with(@id, 'user_')] finds inputs whose id begins with 'user_', like 'user_123' or 'user_name'. This is useful when elements share a common prefix but differ after.
Result
You can locate elements by matching the start of attribute or text values.
Knowing starts-with() allows targeting groups of elements with common prefixes efficiently.
5
IntermediateCombining contains() and starts-with()
🤔
Concept: You can combine these functions to create precise selectors.
Example: //button[contains(@class, 'btn') and starts-with(@id, 'submit')] finds buttons with class containing 'btn' and id starting with 'submit'. Combining filters narrows down elements precisely.
Result
You can write complex XPath expressions that are both flexible and specific.
Combining functions increases selector power and reduces false matches.
6
AdvancedHandling Dynamic Attributes with XPath Functions
🤔Before reading on: do you think contains() and starts-with() can handle attributes that change every time the page loads? Commit to your answer.
Concept: These functions help handle dynamic or partially changing attribute values in real web pages.
Many web apps generate dynamic IDs like 'user_12345'. Using starts-with(@id, 'user_') lets tests find these elements without exact IDs. Similarly, contains() helps when attributes have variable parts anywhere inside.
Result
Tests become more stable and less brittle against UI changes.
Understanding dynamic attribute handling is key to writing maintainable automated tests.
7
ExpertPerformance and Limitations of XPath Functions
🤔Before reading on: do you think using contains() and starts-with() always improves test speed? Commit to your answer.
Concept: Using these functions can impact performance and sometimes cause false positives if not used carefully.
XPath engines evaluate functions at runtime, which can slow down tests if overused on large DOMs. Also, contains() may match unintended elements if the substring is common. Experts balance flexibility with precision and may combine XPath with CSS selectors or JavaScript for best results.
Result
You learn when to use these functions and when to avoid them for efficient, reliable tests.
Knowing the tradeoffs prevents slow or flaky tests and guides smarter locator strategies.
Under the Hood
XPath expressions are parsed and evaluated by the browser or automation tool's XPath engine. Functions like contains() and starts-with() are implemented as string operations that check attribute or text node values during evaluation. The engine traverses the DOM tree, applies the function filters, and returns matching nodes.
Why designed this way?
XPath was designed to query XML documents flexibly. Functions like contains() and starts-with() were added to allow partial matching because exact matches are often too rigid for real-world documents, especially dynamic web pages. This design balances expressiveness and simplicity.
DOM Tree Traversal with XPath Functions

┌─────────────┐
│   DOM Root  │
└─────┬───────┘
      │
┌─────▼───────┐
│ Traverse    │
│ each node   │
└─────┬───────┘
      │
┌─────▼─────────────┐
│ Apply XPath       │
│ function filter   │
│ (contains/starts) │
└─────┬─────────────┘
      │
┌─────▼─────────────┐
│ Return matching   │
│ nodes to caller   │
└───────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does contains() only match the start of a string? Commit to yes or no.
Common Belief:contains() matches only the beginning of a string, like starts-with().
Tap to reveal reality
Reality:contains() matches the substring anywhere inside the string, not just at the start.
Why it matters:Misusing contains() as if it matches only prefixes can cause missed elements or incorrect selectors.
Quick: Can starts-with() match substrings in the middle of an attribute? Commit to yes or no.
Common Belief:starts-with() can find substrings anywhere in the attribute value.
Tap to reveal reality
Reality:starts-with() only matches if the attribute value begins exactly with the given substring.
Why it matters:Assuming starts-with() matches anywhere leads to selectors that never find elements, causing test failures.
Quick: Does using contains() always make tests faster? Commit to yes or no.
Common Belief:Using contains() makes element selection faster because it is flexible.
Tap to reveal reality
Reality:contains() can slow down XPath evaluation because it requires substring checks on many nodes.
Why it matters:Overusing contains() can make tests slower and less efficient, especially on large pages.
Quick: Can contains() cause false positives if the substring is common? Commit to yes or no.
Common Belief:contains() always finds exactly the intended elements without errors.
Tap to reveal reality
Reality:contains() may match unintended elements if the substring appears in multiple places.
Why it matters:False positives cause flaky tests that pass or fail unpredictably, reducing test reliability.
Expert Zone
1
Using contains() on long attribute values can degrade performance; prefer starts-with() when possible for efficiency.
2
Combining contains() with other attribute checks reduces false positives and improves selector precision.
3
XPath functions do not support case-insensitive matching natively; testers must handle case variations manually or with other tools.
When NOT to use
Avoid contains() and starts-with() when exact attribute values are stable and known; use exact matches for faster and clearer selectors. For complex dynamic content, consider CSS selectors or JavaScript-based locators as alternatives.
Production Patterns
In real-world Selenium tests, testers use starts-with() to handle dynamic IDs with common prefixes and contains() to match partial class names or text fragments. They combine these with other XPath filters and wait conditions to build robust, maintainable tests.
Connections
Regular Expressions
Both provide pattern matching to find parts of strings.
Understanding XPath functions helps grasp how pattern matching works in other domains like regex, which is more powerful but also more complex.
SQL LIKE Operator
XPath contains() is similar to SQL's LIKE '%value%' pattern matching.
Knowing this connection helps testers understand partial matching concepts across querying languages.
Human Pattern Recognition
Both involve recognizing partial patterns to identify objects or information.
This connection shows how computers mimic human ability to find things by partial clues, making automation smarter.
Common Pitfalls
#1Using contains() with very common substrings causing many matches.
Wrong approach://div[contains(@class, 'a')]
Correct approach://div[contains(@class, 'btn-primary')]
Root cause:Choosing too generic a substring leads to many unintended matches, making tests flaky.
#2Using starts-with() expecting it to match substrings in the middle.
Wrong approach://input[starts-with(@id, '123')]
Correct approach://input[contains(@id, '123')]
Root cause:Misunderstanding starts-with() behavior causes selectors to fail when substring is not at the start.
#3Overusing contains() on large DOMs causing slow test execution.
Wrong approach://span[contains(@data-info, 'value')]
Correct approach://span[starts-with(@data-info, 'value')]
Root cause:Not considering performance impact of substring searches on many nodes.
Key Takeaways
XPath functions contains() and starts-with() enable flexible element selection by matching parts of attribute or text values.
contains() matches substrings anywhere inside a string, while starts-with() matches only at the beginning.
Using these functions helps handle dynamic or partially changing attributes common in modern web pages.
Overusing these functions can slow down tests or cause false positives; balance flexibility with precision.
Combining these functions with other XPath filters creates robust and maintainable selectors for real-world automation.

Practice

(1/5)
1. Which XPath function would you use to locate elements whose attribute contains a specific substring anywhere within it?
easy
A. starts-with()
B. ends-with()
C. contains()
D. equals()

Solution

  1. Step 1: Understand the purpose of contains()

    The contains() function checks if an attribute or text contains a given substring anywhere inside it.
  2. Step 2: Compare with other functions

    starts-with() checks only the beginning, ends-with() is not standard XPath 1.0, and equals() is not an XPath function.
  3. Final Answer:

    contains() -> Option C
  4. Quick Check:

    Substring anywhere = contains() [OK]
Hint: Use contains() for substring anywhere inside attribute [OK]
Common Mistakes:
  • Confusing contains() with starts-with()
  • Using ends-with() which is not standard XPath 1.0
  • Trying to use equals() as XPath function
2. Which of the following is the correct XPath syntax to find a button element whose id attribute starts with "submit"?
easy
A. //button[contains(@id, 'submit')]
B. //button[@id*='submit']
C. //button[@id^='submit']
D. //button[starts-with(@id, 'submit')]

Solution

  1. Step 1: Identify the correct XPath function for 'starts with'

    The function starts-with() is used to check if an attribute starts with a substring.
  2. Step 2: Check syntax correctness

    //button[starts-with(@id, 'submit')] is correct XPath syntax. Options B and C use invalid XPath operators.
  3. Final Answer:

    //button[starts-with(@id, 'submit')] -> Option D
  4. Quick Check:

    Starts with = starts-with() [OK]
Hint: Use starts-with(@attr, 'text') for prefix matching [OK]
Common Mistakes:
  • Using contains() instead of starts-with() for prefix
  • Using CSS selector syntax like ^= in XPath
  • Incorrect function syntax or missing parentheses
3. Given the following HTML snippet:
<input type="text" id="user_email" value="test@example.com"/>

What is the result of this XPath query?
//*[@id[contains(., 'user')]]
medium
A. Syntax error due to incorrect XPath function usage
B. Selects all elements with any id attribute
C. Selects the input element because its id contains 'user'
D. Selects no elements because 'user' is not in the value attribute

Solution

  1. Step 1: Analyze the XPath syntax

    The XPath //*[@id[contains(., 'user')]] is syntactically incorrect because @id is an attribute node and cannot be used as a function or have predicates applied directly like this.
  2. Step 2: Correct XPath syntax

    To check if the id attribute contains 'user', the correct XPath is //*[@id[contains(., 'user')]] is invalid; instead use //*[contains(@id, 'user')].
  3. Final Answer:

    Syntax error due to incorrect XPath function usage -> Option A
  4. Quick Check:

    Attribute predicates must be correctly formed [OK]
Hint: Use contains(@id, 'user') not @id[contains()] [OK]
Common Mistakes:
  • Using predicates directly on attribute nodes
  • Assuming . refers to attribute value in this context
  • Incorrect predicate syntax
4. You wrote this XPath to find links starting with "http":
//a[contains(starts-with(@href, 'http'))]
Why does this XPath fail to find any elements?
medium
A. Because @href attribute is missing
B. Because contains() cannot wrap starts-with() function
C. Because starts-with() requires two arguments
D. Because the syntax is correct but no links start with 'http'

Solution

  1. Step 1: Understand function nesting rules in XPath

    The contains() function expects two string arguments, but here it wraps starts-with() which returns a boolean, causing a syntax error.
  2. Step 2: Correct usage

    Use either starts-with(@href, 'http') alone or contains(@href, 'http'), but not nested.
  3. Final Answer:

    Because contains() cannot wrap starts-with() function -> Option B
  4. Quick Check:

    Do not nest contains() and starts-with() [OK]
Hint: Do not nest XPath functions like contains(starts-with()) [OK]
Common Mistakes:
  • Nesting contains() and starts-with() incorrectly
  • Assuming starts-with() returns string for contains()
  • Ignoring function argument requirements
5. You want to locate all <div> elements whose class attribute starts with "alert" but excludes those that contain "dismiss" anywhere in the class. Which XPath expression correctly achieves this?
hard
A. //div[starts-with(@class, 'alert') and not(contains(@class, 'dismiss'))]
B. //div[contains(@class, 'alert') and not(starts-with(@class, 'dismiss'))]
C. //div[starts-with(@class, 'alert') or not(contains(@class, 'dismiss'))]
D. //div[contains(@class, 'alert') or contains(@class, 'dismiss')]

Solution

  1. Step 1: Use starts-with() to match class beginning

    The expression starts-with(@class, 'alert') selects elements whose class attribute begins with "alert".
  2. Step 2: Exclude elements containing 'dismiss'

    The not(contains(@class, 'dismiss')) excludes elements whose class contains "dismiss" anywhere.
  3. Step 3: Combine conditions with and

    Both conditions must be true, so use and to combine them.
  4. Final Answer:

    //div[starts-with(@class, 'alert') and not(contains(@class, 'dismiss'))] -> Option A
  5. Quick Check:

    Starts with alert AND no dismiss = //div[starts-with(@class, 'alert') and not(contains(@class, 'dismiss'))] [OK]
Hint: Combine starts-with() and not(contains()) with and [OK]
Common Mistakes:
  • Using or instead of and causing wrong matches
  • Mixing contains() and starts-with() incorrectly
  • Forgetting to negate contains() for exclusion
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