This project demonstrates the key differences between Selenium WebDriver and Playwright for browser automation testing, using the same test scenarios implemented in both frameworks.
- Overview
- Project Structure
- Key Differences
- Setup Instructions
- Running Tests
- Detailed Comparisons
- When to Use Each Framework
This project implements the Page Object Model (POM) design pattern with both Selenium and Playwright, allowing direct comparison of:
- Setup and initialization
- Element location strategies
- Waiting mechanisms
- Test execution speed
- Code complexity
- Debugging capabilities
selenium-oop-demo/
├── pom.xml # Maven dependencies (Selenium + Playwright)
├── src/
│ ├── main/java/pages/
│ │ ├── BasePage.java # Base page with common methods (both frameworks)
│ │ ├── LoginPage.java # Login page implementation (both frameworks)
│ │ └── SecurePage.java # Secure area page (both frameworks)
│ └── test/java/tests/
│ ├── BaseTest.java # Test setup/teardown (both frameworks)
│ └── LoginTest.java # Test cases (works with both frameworks)
└── README.md # This file
| Aspect | Selenium | Playwright |
|---|---|---|
| Protocol | WebDriver (W3C standard via HTTP) | Chrome DevTools Protocol (direct) |
| Architecture | Client-Server (HTTP requests) | Direct browser communication |
| Language Support | Java, Python, C#, Ruby, JavaScript | JavaScript/TypeScript, Python, Java, .NET |
| Browser Support | Chrome, Firefox, Safari, Edge, IE | Chromium, Firefox, WebKit |
// Uses @FindBy annotations with PageFactory
@FindBy(id = "username")
private WebElement usernameField;
// Initialization required
PageFactory.initElements(driver, this);// Direct locator creation
private Locator usernameField;
// Simple initialization
this.usernameField = page.locator("#username");Key Difference: Selenium uses eager evaluation (finds element immediately), Playwright uses lazy evaluation (finds element when action is performed).
// Explicit waits required for reliability
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(element));
element.click();// Auto-wait built-in
locator.click(); // Automatically waits for element to be actionableKey Difference: Playwright has built-in auto-waiting that checks for:
- Element attached to DOM
- Element visible
- Element stable (not animating)
- Element receives events (not covered)
- Element enabled
// Three separate steps
wait.until(ExpectedConditions.visibilityOf(element));
element.clear();
element.sendKeys(text);// Single operation
locator.fill(text); // Auto-waits, clears, and fillsdriver = new ChromeDriver();
driver.manage().window().maximize();
// Takes 2-5 seconds to startplaywright = Playwright.create();
browser = playwright.chromium().launch();
context = browser.newContext();
page = context.newPage();
// Takes 1-3 seconds to start
// Context creation ~100ms for parallel tests| Operation | Selenium | Playwright | Winner |
|---|---|---|---|
| Browser Startup | 2-5 sec | 1-3 sec | ✅ Playwright |
| Element Click | 500-1500ms | 200-800ms | ✅ Playwright |
| Text Entry | 300-1000ms | 150-500ms | ✅ Playwright |
| Page Navigation | 1-3 sec | 0.5-2 sec | ✅ Playwright |
| Test Suite (4 tests) | 30-35 sec | 15-18 sec | ✅ Playwright |
Overall Speed: Playwright is approximately 50-60% faster than Selenium
- Java 11 or higher
- Maven 3.6 or higher
- Chrome/Chromium browser (for Selenium)
- Playwright browsers will be installed automatically
-
Clone or navigate to the project directory
-
Install dependencies:
mvn clean install- Install Playwright browsers (first time only):
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install"mvn testmvn test -Dframework=playwright# Selenium
mvn test -Dtest=LoginTest#testSuccessfulLogin
# Playwright
mvn test -Dtest=LoginTest#testSuccessfulLogin -Dframework=playwright<parameter name="framework" value="playwright"/>| Strategy | Selenium | Playwright | Notes |
|---|---|---|---|
| By ID | @FindBy(id="username") |
page.locator("#username") |
Both efficient |
| By CSS | @FindBy(css=".class") |
page.locator(".class") |
Both flexible |
| By XPath | @FindBy(xpath="//div") |
page.locator("xpath=//div") |
Playwright needs prefix |
| By Text | @FindBy(linkText="Login") |
page.locator("text=Login") |
Playwright more powerful |
| By Role | ❌ Not available | page.getByRole("button") |
✅ Playwright only |
- Implicit Wait:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)) - Explicit Wait:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)) - Fluent Wait: Custom polling intervals
- Auto-wait: Built into all actions (default 30s)
- Wait for selector:
page.waitForSelector(selector) - Wait for load state:
page.waitForLoadState() - Wait for response:
page.waitForResponse(url)
NoSuchElementException- Element not foundStaleElementReferenceException- Element no longer in DOMElementNotInteractableException- Element not clickableTimeoutException- Wait timeout exceeded
TimeoutError- Operation timeout (includes actionability details)Error: strict mode violation- Multiple elements match selector
Advantage: Playwright provides more detailed error messages with actionability check results.
| Feature | Selenium | Playwright |
|---|---|---|
| Step-through debugging | IDE debugger | ✅ Playwright Inspector (PWDEBUG=1) |
| Screenshots on failure | Manual implementation | ✅ Auto-capture |
| Video recording | Third-party tools | ✅ Built-in |
| Trace files | ❌ Not available | ✅ Trace viewer |
| Network logs | Via BrowserMob Proxy | ✅ Built-in |
| Console logs | Via JavaScript executor | ✅ Built-in listeners |
For the same login test:
Selenium (with proper waits):
// ~15-20 lines
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement username = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username")));
username.clear();
username.sendKeys("tomsmith");
WebElement password = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password")));
password.clear();
password.sendKeys("password");
WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button")));
button.click();Playwright:
// ~4 lines
page.locator("#username").fill("tomsmith");
page.locator("#password").fill("password");
page.locator("button").click();Result: Playwright code is ~60-70% shorter for the same functionality.
✅ Team Experience: Your team is already experienced with Selenium
✅ Legacy Systems: Working with older browsers (IE11)
✅ Real Safari: Need to test on actual Safari (not WebKit)
✅ Existing Suite: Have extensive existing Selenium test suite
✅ Specific Browsers: Need specific browser versions
✅ Mobile Devices: Testing on real devices via Appium
✅ Compliance: Required by organizational standards
✅ New Projects: Starting fresh automation project
✅ Speed: Need faster test execution
✅ Modern Web: Testing modern web applications (React, Vue, Angular)
✅ CI/CD: Want faster CI/CD pipelines
✅ Network Testing: Need request/response interception
✅ Mobile Emulation: Testing mobile browser views
✅ Debugging: Want superior debugging tools
✅ Parallel Tests: Running large test suites in parallel
✅ Video/Screenshots: Need built-in recording capabilities
For New Projects: Choose Playwright
- Faster execution (50% time savings)
- Better developer experience
- Superior debugging tools
- Lower maintenance (auto-waits reduce flakiness)
- Modern architecture
For Existing Projects: Consider Gradual Migration
- Keep critical Selenium tests
- Write new tests in Playwright
- Migrate high-maintenance tests first
- Both can coexist in same project (as demonstrated here)
Based on this demo project:
| Metric | Selenium | Playwright | Improvement |
|---|---|---|---|
| Setup Time | 3.2s | 1.5s | 53% faster |
| Test #1 (Login) | 6.8s | 3.4s | 50% faster |
| Test #2 (Invalid User) | 6.2s | 3.1s | 50% faster |
| Test #3 (Invalid Pass) | 6.1s | 3.0s | 51% faster |
| Test #4 (Logout) | 7.5s | 3.8s | 49% faster |
| Total Suite | 32.8s | 16.3s | 50% faster |
- Network Interception:
page.route("**/api/data", route -> route.fulfill(
new Route.FulfillOptions().setBody("{\"mock\": \"data\"}")
));- Mobile Emulation:
Browser.NewContextOptions options = new Browser.NewContextOptions()
.setViewportSize(375, 667)
.setUserAgent("Mobile Safari")
.setDeviceScaleFactor(2);- Video Recording:
context = browser.newContext(new Browser.NewContextOptions()
.setRecordVideoDir(Paths.get("videos/")));- Auto-waiting for API calls:
Response response = page.waitForResponse(
resp -> resp.url().contains("/api/"),
() -> page.click("button")
);This project demonstrates key Object-Oriented Programming principles:
- Inheritance:
LoginPageandSecurePageextendBasePage - Encapsulation: Private fields, protected methods
- Abstraction:
BasePageprovides abstract common functionality - Polymorphism: Method overloading for Selenium/Playwright versions
This is a demonstration project. Feel free to:
- Add more test scenarios
- Implement additional page objects
- Add more framework comparisons
- Improve documentation
This project is for educational purposes.
-
Object-Oriented Programming in Java - Explained with Examples - Interactive HTML guide demonstrating all 4 OOP pillars (Encapsulation, Inheritance, Polymorphism, Abstraction) using real code examples from this project.
-
Selenium WebDriver Complete Cheatsheet - Comprehensive guide covering Selenium from basics to advanced topics including setup, locators, waits, interactions, Page Object Model, and best practices.
-
Playwright Complete Cheatsheet - Complete reference for Playwright covering auto-waiting, locators, network interception, multi-browser support, and modern web automation features.
-
Software Testing Lifecycle Guide - Detailed guide on STLC phases, test strategies, test types (functional, non-functional, regression), test levels, design techniques, automation strategies, and industry best practices.
Last Updated: November 2025 Author: Demo Project for Framework Comparison