0
0
Selenium Pythontesting~15 mins

Page class structure in Selenium Python - Deep Dive

Choose your learning style9 modes available
Overview - Page class structure
What is it?
A Page class structure is a way to organize code that tests websites. It groups all the parts and actions of a single web page into one class. This makes tests easier to read and maintain because each page has its own clear set of instructions. It helps testers work faster and avoid repeating code.
Why it matters
Without a Page class structure, test code becomes messy and hard to fix. Testers would repeat the same steps many times, making mistakes more likely. When the website changes, fixing tests would take much longer. Using this structure saves time, reduces errors, and makes teamwork smoother.
Where it fits
Before learning this, you should know basic Python and how to use Selenium to find and interact with web elements. After this, you can learn about test frameworks like pytest and how to write full test cases using Page classes.
Mental Model
Core Idea
A Page class groups all the elements and actions of one web page into a single, reusable object to keep test code clean and easy to maintain.
Think of it like...
It's like having a toolbox for each room in your house. Instead of searching the whole house for a hammer, you go to the toolbox in the kitchen for kitchen tools or the toolbox in the garage for garage tools. Each toolbox holds everything you need for that room.
┌─────────────────────────────┐
│        Page Class           │
├─────────────┬───────────────┤
│ Elements    │ Actions       │
│ (locators)  │ (methods)     │
│             │               │
│ - Button    │ - click_button() │
│ - Textbox   │ - enter_text()   │
│ - Label     │ - get_label()    │
└─────────────┴───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Web Elements and Locators
🤔
Concept: Learn what web elements are and how to find them using locators in Selenium.
Web elements are parts of a web page like buttons, text boxes, or links. Selenium finds these using locators such as ID, name, class, or XPath. For example, driver.find_element(By.ID, 'submit') finds the submit button.
Result
You can identify and interact with parts of a web page in your test code.
Knowing how to find elements is the base for any web test automation.
2
FoundationBasic Python Classes for Grouping Code
🤔
Concept: Learn how to create simple Python classes to group related code together.
A Python class is like a blueprint for an object. It can hold data (variables) and actions (methods). For example, class Car: def start(self): print('Car started') groups the start action with the Car object.
Result
You can organize code into reusable blocks that represent real-world things.
Grouping related code into classes makes programs easier to understand and reuse.
3
IntermediateCreating a Page Class with Locators
🤔Before reading on: do you think locators should be inside or outside the Page class? Commit to your answer.
Concept: Put all locators for a page inside the Page class as variables to keep them organized.
Inside a Page class, define locators as class variables using tuples, e.g., USERNAME = (By.ID, 'username'). This keeps all element identifiers in one place, making updates easier when the page changes.
Result
All locators for a page are stored clearly inside one class.
Centralizing locators prevents duplication and simplifies maintenance when web pages update.
4
IntermediateAdding Methods for Page Actions
🤔Before reading on: should methods in a Page class interact directly with Selenium or return data? Commit to your answer.
Concept: Add methods in the Page class that perform actions on the page using the locators.
Methods like enter_username(self, name) use the locator USERNAME to find the element and send keys. This hides Selenium details from test scripts and provides clear actions like login_page.enter_username('user').
Result
Test code can call simple methods to interact with the page without repeating Selenium commands.
Encapsulating actions in methods makes tests cleaner and easier to read.
5
IntermediateUsing the Page Class in Test Scripts
🤔
Concept: Learn how to create and use Page class objects in your test code.
In test scripts, create an instance of the Page class and call its methods. For example, login_page = LoginPage(driver); login_page.enter_username('user'). This separates test logic from page details.
Result
Tests become shorter, clearer, and easier to maintain.
Separating test steps from page details reduces duplication and improves test clarity.
6
AdvancedHandling Page Navigation and Returns
🤔Before reading on: do you think a method that clicks a login button should return a new Page object or nothing? Commit to your answer.
Concept: Methods that cause page changes should return new Page class objects representing the new page.
For example, a login method clicks the button and returns a HomePage object. This models the real user flow and helps tests chain actions naturally.
Result
Test code can follow page flows by chaining method calls and Page objects.
Modeling page transitions as object returns mirrors real user navigation and improves test design.
7
ExpertDesigning for Maintainability and Scalability
🤔Before reading on: do you think all locators and methods belong in one big Page class or should they be split? Commit to your answer.
Concept: Split large pages into smaller components or use inheritance to share common code for better maintainability.
For complex pages, create component classes for repeated parts like menus or forms. Use base Page classes for shared methods. This reduces duplication and eases updates.
Result
Test code stays clean and scalable even as the application grows.
Breaking pages into components and using inheritance prevents code bloat and simplifies maintenance in large projects.
Under the Hood
The Page class holds locators as tuples and methods that use Selenium WebDriver to find elements and perform actions. When a method runs, it calls driver.find_element with the locator, interacts with the element, and may return data or new Page objects. This wraps Selenium calls inside Python objects, hiding complexity from test scripts.
Why designed this way?
This design was created to solve the problem of duplicated and fragile test code. By grouping page details and actions, it isolates changes to one place when the UI updates. Alternatives like writing raw Selenium in tests were error-prone and hard to maintain, so the Page class pattern became a best practice.
┌───────────────┐       ┌───────────────┐
│   Test Code   │──────▶│  Page Class   │
│ (calls methods│       │ (holds locators│
│  like login())│       │  and actions) │
└───────────────┘       └──────┬────────┘
                                │
                                ▼
                      ┌───────────────────┐
                      │ Selenium WebDriver│
                      │ (finds elements,  │
                      │  clicks, types)   │
                      └───────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Is it okay to put test assertions inside Page class methods? Commit to yes or no.
Common Belief:Some think Page classes should include test checks and assertions to verify page state.
Tap to reveal reality
Reality:Page classes should only handle page interactions, not test assertions. Assertions belong in test scripts.
Why it matters:Mixing assertions into Page classes makes code harder to reuse and maintain, and blurs responsibilities.
Quick: Do you think storing locators as strings is better than tuples? Commit to your answer.
Common Belief:Some believe storing locators as plain strings is simpler and enough.
Tap to reveal reality
Reality:Locators should be stored as tuples like (By.ID, 'value') to work correctly with Selenium methods.
Why it matters:Using strings alone breaks locator usage and causes runtime errors.
Quick: Should Page classes directly create WebDriver instances? Commit to yes or no.
Common Belief:Some think Page classes should create and manage WebDriver instances themselves.
Tap to reveal reality
Reality:WebDriver should be created outside and passed into Page classes to keep code flexible and testable.
Why it matters:Creating WebDriver inside Page classes makes tests hard to control and reuse.
Quick: Do you think one big Page class per application is better than many small ones? Commit to your answer.
Common Belief:Some believe having one large Page class for the whole app is simpler.
Tap to reveal reality
Reality:Each page should have its own Page class to keep code organized and maintainable.
Why it matters:Big classes become confusing and hard to update, slowing down test development.
Expert Zone
1
Page classes often use lazy loading for elements, finding them only when needed to avoid stale element errors.
2
Using explicit waits inside Page methods improves test stability by waiting for elements to be ready before interacting.
3
Advanced Page classes can include logging and error handling to provide better debugging information during test failures.
When NOT to use
Page class structure is less useful for very simple or one-off tests where overhead is not justified. For API testing or non-UI tests, other patterns like service objects or direct calls are better.
Production Patterns
In real projects, Page classes are combined with test frameworks like pytest and continuous integration. They often use base classes for common features and component classes for reusable page parts. Tests call Page methods to perform flows, improving readability and reducing maintenance.
Connections
Object-Oriented Programming
Page classes are an application of OOP principles like encapsulation and abstraction.
Understanding OOP helps grasp why grouping page elements and actions into classes improves code structure and reuse.
Single Responsibility Principle (SRP)
Page classes follow SRP by having one reason to change: the web page they represent.
Knowing SRP explains why separating page logic from test logic reduces bugs and eases maintenance.
Human Factors in User Interface Design
Page classes model user interactions with UI elements, reflecting how humans navigate pages.
Understanding user behavior helps design Page methods that mimic real user actions, making tests more realistic.
Common Pitfalls
#1Mixing test assertions inside Page class methods.
Wrong approach:class LoginPage: def verify_login(self): assert 'Welcome' in self.driver.page_source # wrong: assertion inside page class
Correct approach:class LoginPage: def is_logged_in(self): return 'Welcome' in self.driver.page_source # In test script: assert login_page.is_logged_in() # assertion in test
Root cause:Confusing responsibilities between page interaction and test verification.
#2Hardcoding locators as strings without using Selenium's By.
Wrong approach:USERNAME = 'username' # wrong: missing locator type self.driver.find_element(USERNAME).send_keys('user')
Correct approach:from selenium.webdriver.common.by import By USERNAME = (By.ID, 'username') self.driver.find_element(*USERNAME).send_keys('user')
Root cause:Not understanding how Selenium expects locators as tuples.
#3Creating WebDriver inside Page class constructor.
Wrong approach:class LoginPage: def __init__(self): self.driver = webdriver.Chrome() # wrong: driver created inside page
Correct approach:class LoginPage: def __init__(self, driver): self.driver = driver # driver passed in from test
Root cause:Not separating test setup from page logic.
Key Takeaways
Page class structure organizes web page elements and actions into one place, making tests cleaner and easier to maintain.
Locators should be stored as tuples inside the Page class, and methods should perform actions without mixing test assertions.
Page classes should receive WebDriver instances from outside to keep code flexible and testable.
Modeling page navigation by returning new Page objects reflects real user flows and improves test design.
Splitting large pages into components and using inheritance helps maintainability in complex projects.