Bird
Raised Fist0
Selenium Pythontesting~15 mins

Element locators in page class in Selenium Python - Deep Dive

Choose your learning style10 modes available
Overview - Element locators in page class
What is it?
Element locators in a page class are ways to find parts of a web page, like buttons or text boxes, so tests can interact with them. A page class is a Python class that groups these locators and actions for one web page, making tests easier to write and maintain. Locators use methods like ID, name, or XPath to point to elements on the page. This helps testers write clear, reusable code to check if a website works correctly.
Why it matters
Without element locators in a page class, test code would be messy and hard to fix when the website changes. Tests would repeat the same code to find elements everywhere, making them slow and error-prone. Using locators in a page class saves time, reduces mistakes, and helps teams keep tests working as websites evolve. This makes testing faster and more reliable, so users get better software.
Where it fits
Before learning element locators in a page class, you should know basic Selenium commands and how to write simple tests in Python. After this, you can learn about advanced page object patterns, test frameworks like pytest, and how to handle dynamic web elements or waits. This topic is a key step in writing clean, maintainable automated UI tests.
Mental Model
Core Idea
Element locators in a page class act like a map and toolbox that help tests find and use parts of a web page easily and clearly.
Think of it like...
It's like having a labeled toolbox for fixing a bike: each tool (locator) is stored in a specific spot (page class), so you always know where to find it when you need to fix something.
Page Class Structure
┌───────────────────────────┐
│       PageClass           │
│ ┌───────────────────────┐ │
│ │ Element Locators      │ │
│ │ - username_field      │ │
│ │ - password_field      │ │
│ │ - login_button        │ │
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ Actions (methods)     │ │
│ │ - enter_username()    │ │
│ │ - enter_password()    │ │
│ │ - click_login()       │ │
│ └───────────────────────┘ │
└───────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Web Element Locators
🤔
Concept: Learn what element locators are and how they identify parts of a web page.
Element locators are instructions that tell Selenium how to find a specific part of a web page. Common locators include ID, name, class name, tag name, CSS selector, and XPath. For example, locating a button by its ID means Selenium looks for the HTML element with that ID attribute.
Result
You can find and interact with web elements reliably using locators.
Knowing how locators work is the foundation for automating web tests because you must find elements before you can test or interact with them.
2
FoundationWhat is a Page Class in Testing?
🤔
Concept: Introduce the page class as a way to organize locators and actions for one web page.
A page class groups all the locators and functions related to a single web page into one Python class. This keeps test code clean and reusable. Instead of writing locators everywhere, you define them once in the page class and call methods to interact with the page.
Result
Tests become easier to read and maintain because page details are in one place.
Organizing locators in a page class reduces duplication and makes tests more stable when the web page changes.
3
IntermediateDefining Locators as Class Variables
🤔Before reading on: do you think locators should be inside methods or as class variables? Commit to your answer.
Concept: Learn to define locators as class variables using Selenium's By class for clarity and reuse.
In the page class, locators are usually stored as class variables using tuples like (By.ID, 'element_id'). This makes them easy to find and update. For example: from selenium.webdriver.common.by import By class LoginPage: username_field = (By.ID, 'username') password_field = (By.ID, 'password') login_button = (By.ID, 'loginBtn')
Result
Locators are clearly defined and easy to reference in methods.
Storing locators as class variables separates element identification from actions, improving code clarity and maintainability.
4
IntermediateUsing Locators in Page Methods
🤔Before reading on: do you think page methods should find elements every time or store elements once? Commit to your answer.
Concept: Use locators inside methods to find elements dynamically when needed, ensuring fresh references.
Page methods use the locators to find elements on the page each time they run. This avoids stale element errors. For example: def enter_username(self, username): element = self.driver.find_element(*self.username_field) element.clear() element.send_keys(username) Here, * unpacks the locator tuple for find_element.
Result
Methods interact with the current page state safely and reliably.
Finding elements inside methods ensures tests work even if the page reloads or changes between actions.
5
IntermediateBenefits of Page Class Locators
🤔
Concept: Understand why using locators in a page class improves test code quality.
Using locators in a page class: - Centralizes element info for easy updates - Makes tests more readable - Reduces duplicated code - Helps separate test logic from page details This leads to faster test maintenance and clearer test scripts.
Result
Test suites become more stable and easier to manage over time.
Centralizing locators prevents widespread test breakage when UI changes, saving time and effort.
6
AdvancedHandling Dynamic Locators in Page Classes
🤔Before reading on: do you think static locators work for all elements, or do some need dynamic parts? Commit to your answer.
Concept: Learn how to create locators that change based on input or page state using methods or formatted strings.
Some elements have IDs or attributes that change, like a list item with a number. To handle this, define locator methods that return a locator tuple with dynamic parts. For example: def get_item_locator(self, item_name): return (By.XPATH, f"//div[text()='{item_name}']") Then use: self.driver.find_element(*self.get_item_locator('Item1'))
Result
Tests can find elements that change without rewriting the whole page class.
Dynamic locators increase page class flexibility and allow tests to handle real-world web pages with changing content.
7
ExpertAvoiding Common Locator Pitfalls in Page Classes
🤔Before reading on: do you think using complex XPath locators is always best, or can simpler locators be better? Commit to your answer.
Concept: Discover best practices and hidden dangers in locator choice and page class design for robust tests.
Experts avoid overly complex or brittle locators like long XPath chains that break easily. Instead, prefer stable attributes like IDs or data-test attributes. Also, avoid storing WebElement objects as class variables because they can become stale. Always find elements fresh in methods. Use waits to handle slow-loading elements. Example of a bad locator: username_field = (By.XPATH, "//div[3]/form/input[1]") Better: username_field = (By.ID, 'username')
Result
Tests become more reliable and easier to maintain in changing environments.
Choosing stable locators and fresh element lookup prevents flaky tests and reduces debugging time.
Under the Hood
When a test calls a page class method, Selenium uses the locator tuple to ask the browser to find the matching element in the current page DOM. The locator tuple unpacks into a method (like By.ID) and a value (like 'username'). Selenium sends this to the browser driver, which queries the page structure and returns a WebElement object. This object represents the live element and allows actions like click or send_keys. If the page changes, the old WebElement becomes invalid, so fresh lookup is needed each time.
Why designed this way?
Page classes with locators were designed to separate test logic from page details, making tests easier to read and maintain. Early Selenium tests mixed locators and test steps everywhere, causing duplication and fragile tests. The page object pattern emerged to organize locators and actions in one place. Using tuples for locators standardizes how elements are found, making code consistent and easier to update when UI changes.
Page Class Locator Flow
┌───────────────┐
│ Test Script   │
│ calls method  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Page Class    │
│ method uses   │
│ locator tuple │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Selenium WebDriver │
│ sends find_element │
│ request to browser │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Browser DOM   │
│ returns WebElement │
└───────────────┘
Myth Busters - 3 Common Misconceptions
Quick: Do you think storing WebElement objects as class variables is a good idea? Commit to yes or no.
Common Belief:Storing WebElement objects as class variables saves time by avoiding repeated lookups.
Tap to reveal reality
Reality:WebElement objects become stale if the page reloads or changes, causing errors. It's better to store locators and find elements fresh each time.
Why it matters:Using stale elements leads to flaky tests that fail unpredictably, wasting debugging time.
Quick: Do you think complex XPath locators are always better than simple ID locators? Commit to yes or no.
Common Belief:Complex XPath locators can find any element, so they are always the best choice.
Tap to reveal reality
Reality:Simple locators like ID or name are more stable and faster. Complex XPath can break easily if the page structure changes.
Why it matters:Relying on brittle locators causes tests to break often, increasing maintenance effort.
Quick: Do you think defining locators inside test methods is better than in a page class? Commit to yes or no.
Common Belief:Defining locators inside test methods keeps tests self-contained and easier to understand.
Tap to reveal reality
Reality:Locators scattered in tests cause duplication and harder maintenance. Centralizing them in page classes improves clarity and reusability.
Why it matters:Scattered locators make updating tests slow and error-prone when UI changes.
Expert Zone
1
Using data-test or custom attributes as locators improves test stability because they are less likely to change than visual or structural attributes.
2
Separating locator definitions from interaction methods allows teams to update locators without touching test logic, enabling parallel work between developers and testers.
3
Dynamic locator methods can accept parameters to handle lists or repeated elements, reducing code duplication and increasing flexibility.
When NOT to use
Page classes with static locators are less effective for highly dynamic single-page applications where elements change frequently or are generated on the fly. In such cases, using component-based testing libraries or direct JavaScript execution might be better. Also, for very simple tests or prototypes, full page classes may add unnecessary complexity.
Production Patterns
In real-world projects, page classes are combined with test frameworks like pytest and use explicit waits to handle slow-loading elements. Teams often create base page classes with common methods and extend them for specific pages. Locators use stable attributes like data-test IDs. Tests call page methods rather than raw Selenium commands, improving readability and reducing duplication.
Connections
Page Object Pattern
Element locators in page classes are a core part of the Page Object Pattern in test automation.
Understanding locators in page classes helps grasp how the Page Object Pattern organizes test code for maintainability and clarity.
Software Design Principles
Using page classes with locators applies the Single Responsibility Principle by separating element identification from test logic.
Knowing this connection shows how good software design improves test code quality and reduces bugs.
Maps and Navigation (Geography)
Locators in page classes act like coordinates on a map, guiding tests to find exact locations on a web page.
Seeing locators as map coordinates helps understand their role in navigating complex page structures.
Common Pitfalls
#1Storing WebElement objects as class variables causing stale element errors.
Wrong approach:class LoginPage: username_element = driver.find_element(By.ID, 'username') def enter_username(self, username): self.username_element.clear() self.username_element.send_keys(username)
Correct approach:class LoginPage: username_field = (By.ID, 'username') def enter_username(self, username): element = self.driver.find_element(*self.username_field) element.clear() element.send_keys(username)
Root cause:Misunderstanding that WebElement objects become invalid if the page reloads or changes.
#2Using brittle XPath locators that break with minor page changes.
Wrong approach:username_field = (By.XPATH, "//div[3]/form/input[1]")
Correct approach:username_field = (By.ID, 'username')
Root cause:Choosing locators based on page structure rather than stable attributes.
#3Defining locators inside test methods causing duplication and maintenance issues.
Wrong approach:def test_login(driver): username = driver.find_element(By.ID, 'username') username.send_keys('user') # repeated in many tests
Correct approach:class LoginPage: username_field = (By.ID, 'username') def enter_username(self, username): element = self.driver.find_element(*self.username_field) element.send_keys(username) # Tests call page.enter_username('user')
Root cause:Not using page classes to centralize locators and actions.
Key Takeaways
Element locators in page classes organize how tests find and interact with web page elements, making tests clearer and easier to maintain.
Storing locators as tuples in class variables and finding elements fresh in methods prevents stale element errors and improves test reliability.
Choosing stable locators like IDs or custom attributes reduces test breakage when the web page changes.
Dynamic locator methods allow tests to handle changing page content flexibly without rewriting page classes.
Avoid brittle locators and scattered element definitions to save time and effort in maintaining automated tests.

Practice

(1/5)
1. What is the main purpose of using element locators in a page class in Selenium Python?
easy
A. To find web elements clearly and reuse them easily
B. To write complex test logic inside the page class
C. To store test data separately from the test scripts
D. To execute browser commands directly

Solution

  1. Step 1: Understand the role of element locators

    Element locators help identify web elements on a page so tests can interact with them.
  2. Step 2: Recognize the benefit of using a page class

    Storing locators in a page class allows easy reuse and keeps code clean.
  3. Final Answer:

    To find web elements clearly and reuse them easily -> Option A
  4. Quick Check:

    Element locators = reuse and clarity [OK]
Hint: Locators in page class = find elements + reuse [OK]
Common Mistakes:
  • Confusing locators with test data storage
  • Thinking page class runs browser commands
  • Assuming locators hold test logic
2. Which of the following is the correct way to define a locator for a button with id 'submit' in a Selenium page class?
easy
A. submit_button = By('id', 'submit')
B. submit_button = By.ID('submit')
C. submit_button = ('id', submit)
D. submit_button = (By.ID, 'submit')

Solution

  1. Step 1: Recall the correct locator tuple format

    Locators are tuples with By strategy and string value, e.g., (By.ID, 'value').
  2. Step 2: Check each option's syntax

    submit_button = (By.ID, 'submit') uses (By.ID, 'submit'), which is correct. Others use wrong syntax or missing quotes.
  3. Final Answer:

    submit_button = (By.ID, 'submit') -> Option D
  4. Quick Check:

    Locator tuple = (By.ID, 'value') [OK]
Hint: Locator = (By.<STRATEGY>, 'value') tuple [OK]
Common Mistakes:
  • Using By.ID('submit') instead of tuple
  • Missing quotes around 'submit'
  • Using wrong tuple structure
3. Given the locator login_button = (By.CSS_SELECTOR, 'button.login') in a page class, what will driver.find_element(*login_button) do?
medium
A. Cause a syntax error because of unpacking
B. Find the first button element with class 'login' on the page
C. Find all button elements with class 'login' on the page
D. Find an element by tag name 'button.login'

Solution

  1. Step 1: Understand the locator tuple and unpacking

    The locator is a tuple (By.CSS_SELECTOR, 'button.login'). Using * unpacks it into two arguments.
  2. Step 2: Know what find_element does

    find_element returns the first matching element, not all elements.
  3. Final Answer:

    Find the first button element with class 'login' on the page -> Option B
  4. Quick Check:

    find_element + CSS selector = first match [OK]
Hint: find_element finds first match, unpack locator tuple [OK]
Common Mistakes:
  • Confusing find_element with find_elements
  • Thinking unpacking causes syntax error
  • Misunderstanding CSS selector as tag name
4. You have this locator in your page class: search_box = (By.NAME, 'q'). Your test code uses driver.find_element(search_box) and fails. What is the error and how to fix it?
medium
A. Error: Missing unpacking operator '*'. Fix: Use driver.find_element(*search_box)
B. Error: Wrong locator type. Fix: Change By.NAME to By.ID
C. Error: Locator value is incorrect. Fix: Change 'q' to 'search'
D. Error: find_element cannot use tuples. Fix: Use string locator only

Solution

  1. Step 1: Identify the cause of failure

    driver.find_element expects two arguments, but passing a tuple without unpacking sends one argument.
  2. Step 2: Apply the correct fix

    Use the unpacking operator * to pass locator as separate arguments: driver.find_element(*search_box).
  3. Final Answer:

    Error: Missing unpacking operator '*'. Fix: Use driver.find_element(*search_box) -> Option A
  4. Quick Check:

    Unpack locator tuple with * [OK]
Hint: Always unpack locator tuple with * in find_element [OK]
Common Mistakes:
  • Not using * causes TypeError
  • Changing locator type unnecessarily
  • Assuming locator value is wrong
5. You want to create a page class locator for a link with text 'Home' that may appear as either an <a> tag or a <button> tag. Which locator is best to find it reliably?
hard
A. home_link = (By.LINK_TEXT, 'Home')
B. home_link = (By.CSS_SELECTOR, 'a.home, button.home')
C. home_link = (By.XPATH, "//a[text()='Home'] | //button[text()='Home']")
D. home_link = (By.ID, 'home')

Solution

  1. Step 1: Understand the locator requirements

    The element can be either an <a> or <button> with text 'Home', so locator must cover both tags.
  2. Step 2: Evaluate locator options

    home_link = (By.XPATH, "//a[text()='Home'] | //button[text()='Home']") uses XPath with OR (|) to match either tag by exact text, which is reliable. home_link = (By.LINK_TEXT, 'Home') only works for <a> tags. home_link = (By.CSS_SELECTOR, 'a.home, button.home') uses classes which may not exist. home_link = (By.ID, 'home') uses ID which is not given.
  3. Final Answer:

    home_link = (By.XPATH, "//a[text()='Home'] | //button[text()='Home']") -> Option C
  4. Quick Check:

    XPath OR matches multiple tags [OK]
Hint: Use XPath OR (|) to match multiple tag types [OK]
Common Mistakes:
  • Using LINK_TEXT misses button tags
  • Using CSS selectors without classes
  • Assuming ID exists without confirmation
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