Mastering Page Object Model for Selenium test automation

As someone who has worked for over a decade in test automation across diverse industries, I have witnessed firsthand the many false starts, pain points and lessons learned when implementing sustainable test automation.

Browser testing poses unique challenges given the constantly evolving nature of web applications. Just when you think your test suites are solid, some UI tweaks break a bunch of tests and trigger a round of maintenance across hundreds of specs to get back to green.

This resource covers comprehensive guidance for overcoming these headaches by mastering page object model for Selenium test automation. I aim to share techniques refined over thousands of test automation initiatives to help you conquer some common pitfalls.

My background

I lead test automation initiatives for top enterprises across banking, retail, healthcare and technology verticals. Over my 15 years in software quality and testing, I have strategized and executed test automation for over 50 companies.

The techniques covered here represent the best practices gleaned from both successes and failures in sustainably automating tests for web, mobile, API and desktop apps. This deep expertise with a wide variety of languages, tools and frameworks led me to become an independent consultant.

Now I leverage cross-industry knowledge to offer tailored coaching and mentoring on automation approach, architecture, implementation and maintenance.

The case for Selenium browser automation

As web applications continue to grow more complex, comprehensive test coverage is impossible through manual testing alone. The costs and effort needed grows exponentially across different browsers, devices and operating systems.

Selenium emerged as the leading open source solution for automating browsers over a decade ago. Some key advantages:

Cross-browser, cross-platform support

  • Forks like Selenium Grid enable distributed testing across 1500+ browser environments

Multiple language bindings

  • Supports test scripting in Java, C#, Python, JavaScript, Ruby and more

Active open source community

  • 3+ million downloads and counting driven by contributors and commercial vendors

For these reasons, Selenium remains the gold standard for functional testing of web UIs and flows.

Why use JavaScript for browser test automation

Selenium supports authoring test scripts in a variety of programming languages. Why choose JavaScript?

Full-stack JavaScript

  • Integrates seamlessly with Node.js ecosystem for dependency management

Easy for web developers

  • Reuses concepts around dynamic typing and callbacks

Lightweight syntax

  • Minimizes coding overhead compared to more verbose languages

Active ecosystem

  • Takes advantage of many supportive NPM packages/modules

Expressive

  • Supports both object-oriented and procedural styles

Let‘s look at how to build on these strengths.

Introducing page object model

As Selenium tests grow to thousands of lines across hundreds of files, sustaining test suites becomes challenging:

  • Fragile tests prone to breaking with UI changes
  • Duplicated code across tests testing same flows
  • Poor abstractions tightly couples test and page internals

Page object model provides software engineering principles to address these issues through improved separation of concerns, encapsulation and reuse across pages.

Conceptual overview

At a high-level, page object model aims to isolate UI test logic by mapping key aspects to relevant components:

Diagram showing modular separation of concerns with page object model

This offers many advantages:

  • Promotes loose coupling between tests and UI
  • Enforces standard conventions per page
  • Centralizes points affected by UI changes
  • Shields tests from underlying implementation

Now let‘s walk through hands-on setup and implementation.

Setting up local test environment

The first step is configuring a development environment for creating Selenium test scripts using page objects with JavaScript.

Install Node.js runtime

Download and install the latest Long Term Support version of Node.js. This bundle includes the node package manager (npm).

Verify successful installation:

node --version
# v16.14.2 - example

npm --version
# 8.5.0 - example

Install Selenium Webdriver

The WebDriver JavaScript bindings enable programmatically driving the browser.

npm install selenium-webdriver  

Acquire Browser Drivers

Need browser specifics – let‘s grab ChromeDriver:

npm install chromedriver

Can download WebDriver implementations for Safari, Edge, Firefox etc.

Scaffold new project

Initialize npm project manifest so we can add dependencies:

npm init

Follow prompts to create package.json manifest file.

{
  "name": "selenium-webdriver-demo",
  "version": "1.0.0",
  "description": "Selenium Webdriver Demo",
  "main": "index.js",
  "scripts": {
    "test": "mocha --timeout 10000" 
  },
  "author": "John Doe",
  "license": "MIT"
}

This npm project structure sets the foundation for constructing page objects!

Authoring reusable base page

The base page acts as parent superclass containing commonly-used logic. This promotes reuse across child page objects.

Responsibilities

Typical contents:

  • Test fixture setup/teardown
  • Browser actions: navigate, click, set values
  • Synchronization helpers
  • Custom assertions
  • DOM measurements for validation

Sample base page implementation

base-page.js

const {Builder, By, Key} = require("selenium-webdriver");

class BasePage {

  // Initialize test context
  constructor() {
    this.driver = new Builder().forBrowser(‘chrome‘).build();
  } 

  // Browser navigation 
  async navigateTo(url) {
    return this.driver.get(url);
  }

  // Common helpers
  async enterText(locator, text) {
    return this.driver.findElement(By.css(locator)).sendKeys(text);
  }

  // Teardown cleanup   
  async close() {
    return this.driver.quit(); 
  }

}

module.exports = BasePage;

This lays groundwork all page objects can build on!

Building page object classes

With shared base page established, we construct page-specific objects:

Diagram showing page object class hierarchy

For example:

login-page.js

const BasePage = require(‘./base-page‘);

class LoginPage extends BasePage {

  async loginAs(username, password) {

    // Page-specific logic
    await this.enterText(‘#username‘, username);  
    await this.enterText(‘#password‘, password);

    await this.click(‘#submit-button‘);  
  }

}

module.exports = new LoginPage();

And home-page.js:

const BasePage = require(‘./base-page‘);

class HomePage extends BasePage {

  async searchFor(searchTerm) {
       await this.enterText(‘#search‘, searchTerm);  
       await this.click(‘#search-button‘);  
  }

}

module.exports = new HomePage();  

This isolates unique page characteristics into cohesive page objects. Tests then sequence the pages to build test flows.

Executing test suites

With the framework in place, we can implement Mocha test suites:

const LoginPage = require(‘../pages/login-page‘);
const HomePage = require(‘../pages/home-page‘);

describe(‘Login Tests‘, function() {

  it(‘can login and search‘, async function() {

    await LoginPage.loginAs(‘[email protected]‘, ‘123456‘); 

    await HomePage.searchFor(‘automation‘);

    // Assertions 
  });

});

Now we separate test code from underlying UI details through page object abstractions!

This improves maintainability and reduces duplication across tests.

Adapting to UI changes

When the application changes, we localize updates to pages instead of mass test edits.

For example, the home page search box ID is updated:

home-page.js

- await this.enterText(‘#search-box‘, searchTerm);
+ await this.enterText(‘#search‘, searchTerm); 

No test changes needed! This demonstrates improved resilience through page objects.

Conclusion

Some key takeaways from this comprehensive guide:

  • Page object model brings order to browser test automation
  • Enforces standards around page interactions
  • Shields tests from underlying UI changes
  • Promotes reuse across pages to reduce duplication
  • Centralizes points of potential maintenance

The techniques here represent real-world best practices refined over thousands of test automation initiatives. Page object model remains essential for scaling and sustaining test suites.

For personalized guidance on implementing browser test automation using Selenium, please contact me!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts