Loading...
Loading...
Expert guidance for browser automation and web testing using Selenium WebDriver with best practices for element location, waits, and test organization.
npx skill4agent add mindrally/skills selenium-automationtests/
conftest.py
pages/
__init__.py
base_page.py
login_page.py
dashboard_page.py
tests/
__init__.py
test_login.py
test_dashboard.py
utils/
__init__.py
driver_factory.py
config.pyfrom selenium import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
def create_driver(browser='chrome', headless=False):
if browser == 'chrome':
options = Options()
if headless:
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
service = Service(ChromeDriverManager().install())
return webdriver.Chrome(service=service, options=options)
# Add other browsers as neededimport pytest
from utils.driver_factory import create_driver
@pytest.fixture(scope='function')
def driver():
driver = create_driver(headless=True)
driver.implicitly_wait(10)
yield driver
driver.quit()from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage:
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def find_element(self, locator):
return self.wait.until(EC.presence_of_element_located(locator))
def click_element(self, locator):
element = self.wait.until(EC.element_to_be_clickable(locator))
element.click()
def enter_text(self, locator, text):
element = self.find_element(locator)
element.clear()
element.send_keys(text)from selenium.webdriver.common.by import By
from pages.base_page import BasePage
class LoginPage(BasePage):
# Locators
USERNAME_INPUT = (By.ID, 'username')
PASSWORD_INPUT = (By.ID, 'password')
LOGIN_BUTTON = (By.CSS_SELECTOR, 'button[type="submit"]')
ERROR_MESSAGE = (By.CLASS_NAME, 'error-message')
def __init__(self, driver):
super().__init__(driver)
self.url = '/login'
def login(self, username, password):
self.enter_text(self.USERNAME_INPUT, username)
self.enter_text(self.PASSWORD_INPUT, password)
self.click_element(self.LOGIN_BUTTON)
def get_error_message(self):
return self.find_element(self.ERROR_MESSAGE).text# Good: Specific, stable selectors
By.CSS_SELECTOR, 'form#login input[name="username"]'
By.CSS_SELECTOR, '[data-testid="submit-button"]'
# Avoid: Fragile selectors
By.CSS_SELECTOR, 'div > div > div > button' # Too structural
By.CSS_SELECTOR, '.btn-primary' # Class might change# Use for complex relationships
By.XPATH, '//label[text()="Email"]/following-sibling::input'
By.XPATH, '//table//tr[contains(., "John")]//button[@class="edit"]'from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
# Wait for element to be clickable
element = wait.until(EC.element_to_be_clickable((By.ID, 'button')))
# Wait for element to be visible
element = wait.until(EC.visibility_of_element_located((By.ID, 'modal')))
# Wait for text to be present
wait.until(EC.text_to_be_present_in_element((By.ID, 'status'), 'Complete'))
# Custom wait condition
wait.until(lambda d: d.find_element(By.ID, 'count').text == '5')presence_of_element_locatedvisibility_of_element_locatedelement_to_be_clickablestaleness_offrame_to_be_available_and_switch_to_itimport pytest
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage
class TestLogin:
@pytest.fixture(autouse=True)
def setup(self, driver):
self.driver = driver
self.login_page = LoginPage(driver)
self.dashboard_page = DashboardPage(driver)
def test_successful_login(self):
"""Verify user can login with valid credentials"""
self.driver.get('https://example.com/login')
self.login_page.login('valid_user', 'valid_pass')
assert self.dashboard_page.is_displayed()
def test_invalid_password_shows_error(self):
"""Verify error message displays for invalid password"""
self.driver.get('https://example.com/login')
self.login_page.login('valid_user', 'wrong_pass')
assert 'Invalid credentials' in self.login_page.get_error_message()test_login_with_valid_credentials_redirects_to_dashboardfrom selenium.webdriver.support.ui import Select
select = Select(driver.find_element(By.ID, 'country'))
select.select_by_visible_text('United States')
select.select_by_value('us')
select.select_by_index(1)alert = driver.switch_to.alert
alert.accept() # Click OK
alert.dismiss() # Click Cancel
alert.send_keys('input text') # Type in promptdriver.switch_to.frame('frame_name')
# Or by element
frame = driver.find_element(By.ID, 'myframe')
driver.switch_to.frame(frame)
# Return to main content
driver.switch_to.default_content()original_window = driver.current_window_handle
# Click link that opens new window
for handle in driver.window_handles:
if handle != original_window:
driver.switch_to.window(handle)
break
# Return to original
driver.switch_to.window(original_window)# pytest.ini
[pytest]
addopts = -v --html=reports/report.html
markers =
smoke: Quick smoke tests
regression: Full regression testsdriver.save_screenshot('debug.png')print(driver.page_source)import pdb; pdb.set_trace()