In the ever-evolving world of software testing, having a well-structured automation framework is crucial for efficient and effective testing. This guide will walk you through setting up a Selenium automation framework using Python, the Page Object Model (POM), and best practices to ensure your framework is modern, maintainable, and scalable.
1. Project Structure
1.1 Directory Layout
A well-organized project structure is fundamental for maintaining clarity and efficiency in your automation framework. Here's a recommended directory layout:/selenium-framework |-- /src | |-- /pageobjects | | |-- login_page.py | | |-- home_page.py | |-- /utils | | |-- browser_factory.py | | |-- config_utils.py |-- /tests | |-- /test_login.py |-- /testdata | |-- testdata.xlsx |-- /reports | |-- /html | |-- /pdf |-- /logs |-- /drivers |-- /scripts |-- requirements.txt |-- .gitignore |-- README.md
2. Framework Components
2.1 Page Object Model (POM)
The Page Object Model is a design pattern that enhances test maintenance and reduces code duplication. Each page is represented as a class, encapsulating the details of the web page and the actions that can be performed on it.Example: login_page.py
pythonfrom selenium.webdriver.common.by import By from selenium.webdriver.remote.webdriver import WebDriver class LoginPage: def __init__(self, driver: WebDriver): self.driver = driver self.username_field = (By.ID, "username") self.password_field = (By.ID, "password") self.login_button = (By.ID, "loginButton") def enter_username(self, username: str): self.driver.find_element(*self.username_field).send_keys(username) def enter_password(self, password: str): self.driver.find_element(*self.password_field).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click()
2.2 Utilities
Utility classes help manage common functionalities across your tests, such as browser setup and configuration management.browser_factory.py
pythonfrom selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.firefox.service import Service as FirefoxService from webdriver_manager.firefox import GeckoDriverManager def start_browser(browser: str): if browser.lower() == "chrome": driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install())) elif browser.lower() == "firefox": driver = webdriver.Firefox(service=FirefoxService(GeckoDriverManager().install())) else: raise ValueError("Browser not supported.") driver.maximize_window() return driver
config_utils.py
pythonimport configparser class ConfigUtils: def __init__(self): self.config = configparser.ConfigParser() self.config.read('config.properties') def get_property(self, section: str, key: str) -> str: return self.config.get(section, key)
2.3 Configuration Management
Configuration management is essential for managing environment-specific settings.config.properties
[Settings] browser = chrome url = https://example.com
2.4 Test Data Management
Test data management is crucial for maintaining relevant and comprehensive test data.testdata.xlsx
An Excel file with test data.2.5 Test Scripts
Test scripts utilize the Page Object Model to perform actions and assertions.test_login.py
pythonimport pytest from selenium import webdriver from src.pageobjects.login_page import LoginPage from src.utils.browser_factory import start_browser from src.utils.config_utils import ConfigUtils @pytest.fixture(scope="module") def setup(): config = ConfigUtils() driver = start_browser(config.get_property('Settings', 'browser')) driver.get(config.get_property('Settings', 'url')) yield driver driver.quit() def test_login(setup): driver = setup login_page = LoginPage(driver) login_page.enter_username("testuser") login_page.enter_password("password") login_page.click_login() # Add assertions here
2.6 Reporting
Reporting is essential for tracking test execution progress and results.pytest-html
Use the pytest-html library to generate HTML reports. Install viapip install pytest-html.Run tests with
pytest --html=reports/html/report.html.
2.7 Logging
Logging helps capture detailed information about test execution for debugging and analysis.Python's logging module
Configure logs to be saved in the/logs directory.
3. Build and Dependency Management
3.1 Requirements
- requirements.txt
selenium==4.23.1 webdriver-manager==3.8.6 pytest==7.3.1 pytest-html==3.2.0
-
Install dependencies with
pip install -r requirements.txt.
4. Execution and Continuous Integration
4.1 Test Execution
Use pytest for running tests.Configure parallel test execution if needed with pytest-xdist.
4.2 Continuous Integration (CI)
Create a CI/CD pipeline configuration (e.g., GitHub Actions, Jenkinsfile).Include steps for building, testing, and reporting.
5. Best Practices
- Version Control: Use Git for version control. Maintain a
.gitignorefile to exclude unnecessary files. - Documentation: Maintain a
README.mdfor framework usage and guidelines. - Modularity: Keep code modular and reusable.
- Maintainability: Follow coding standards and best practices for readability and maintenance.