E2E Testing Development for Websites (Selenium)
Selenium WebDriver is the oldest standard for browser automation. It supports all major browsers, all programming languages, and integrates with TestNG, JUnit, pytest. Chosen when cross-browser compatibility is required via Selenium Grid or when legacy infrastructure already exists.
Selenium 4 + Python (pytest)
# requirements.txt
selenium>=4.0
pytest
pytest-html
# conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture(scope='session')
def driver():
options = Options()
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
driver.set_window_size(1280, 900)
yield driver
driver.quit()
Basic Tests
# tests/test_login.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class TestLogin:
def test_valid_login(self, driver):
driver.get('https://example.com/login')
driver.find_element(By.CSS_SELECTOR, '[data-cy="email"]').send_keys('[email protected]')
driver.find_element(By.CSS_SELECTOR, '[data-cy="password"]').send_keys('password123')
driver.find_element(By.CSS_SELECTOR, '[data-cy="submit"]').click()
wait = WebDriverWait(driver, 10)
wait.until(EC.url_contains('/dashboard'))
assert '/dashboard' in driver.current_url
def test_invalid_login(self, driver):
driver.get('https://example.com/login')
driver.find_element(By.ID, 'email').send_keys('[email protected]')
driver.find_element(By.ID, 'password').send_keys('wrongpass')
driver.find_element(By.XPATH, '//button[@type="submit"]').click()
error = WebDriverWait(driver, 5).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, '.error-message'))
)
assert 'Invalid' in error.text
Page Object Model
# pages/login_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class LoginPage:
URL = '/login'
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def open(self):
self.driver.get(f'https://example.com{self.URL}')
return self
def enter_email(self, email: str):
self.driver.find_element(By.ID, 'email').send_keys(email)
return self
def enter_password(self, password: str):
self.driver.find_element(By.ID, 'password').send_keys(password)
return self
def submit(self):
self.driver.find_element(By.CSS_SELECTOR, 'button[type=submit]').click()
return self
def get_error_message(self) -> str:
element = self.wait.until(EC.visibility_of_element_located((By.CLASS_NAME, 'error')))
return element.text
Selenium 4 + Java (TestNG)
// LoginTest.java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.Assert;
import org.testng.annotations.*;
public class LoginTest {
private WebDriver driver;
@BeforeClass
public void setUp() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
driver = new ChromeDriver(options);
driver.manage().window().setSize(new Dimension(1280, 900));
}
@Test
public void testSuccessfulLogin() {
driver.get("https://example.com/login");
driver.findElement(By.id("email")).sendKeys("[email protected]");
driver.findElement(By.id("password")).sendKeys("password123");
driver.findElement(By.cssSelector("[type='submit']")).click();
Assert.assertTrue(driver.getCurrentUrl().contains("/dashboard"),
"Should redirect to dashboard after login");
}
@AfterClass
public void tearDown() {
if (driver != null) driver.quit();
}
}
Selenium Grid — Parallel Execution
# docker-compose-grid.yml
services:
selenium-hub:
image: selenium/hub:4.18
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome-node:
image: selenium/node-chrome:4.18
environment:
SE_EVENT_BUS_HOST: selenium-hub
depends_on: [selenium-hub]
deploy:
replicas: 3
firefox-node:
image: selenium/node-firefox:4.18
environment:
SE_EVENT_BUS_HOST: selenium-hub
depends_on: [selenium-hub]
# Connecting to Grid
from selenium.webdriver.remote.webdriver import RemoteWebDriver
driver = RemoteWebDriver(
command_executor='http://selenium-hub:4444/wd/hub',
options=ChromeOptions()
)
Implementation Timeline
Setup + Page Objects + 30 test cases: 5–8 days.







