A comprehensive UI automation framework built with Playwright and Python, following the Page Object Model (POM) design pattern with a clear abstraction layer: Tests → Steps → Pages.
playwright_test_fw/
├── pages/ # Page Object Models
│ ├── base_page.py # Base page with common actions
│ ├── login_page.py # Login page object
│ └── home_page.py # Home page object
├── steps/ # Business logic layer
│ └── login_steps.py # Login workflow steps
├── tests/ # Test cases
│ ├── conftest.py # Pytest fixtures and configuration
│ └── test_login.py # Login test scenarios
├── utils/ # Utility modules
│ ├── logger.py # Custom logging implementation
│ └── config.py # Configuration management
├── logs/ # Test execution logs
├── reports/ # Test reports
├── screenshots/ # Failure screenshots
├── videos/ # Test execution videos
├── pytest.ini # Pytest configuration
├── requirements.txt # Python dependencies
└── .env # Environment variables
- Each page is represented as a class
- Page elements (locators) are defined as class attributes
- Page actions are defined as methods
- All pages inherit from
BasePage
Tests (What to test)
↓
Steps (Business Logic)
↓
Pages (UI Interactions)
- Tests: High-level test scenarios focusing on WHAT to test
- Steps: Business logic and workflows (HOW to execute)
- Pages: UI interactions and element manipulations (WHERE to interact)
- Common actions: click, fill, select, check, hover, etc.
- Wait strategies: wait_for_selector, wait_for_url, wait_for_load_state
- Assertions: assert_element_visible, assert_text, assert_url
- Logging: All actions are logged automatically
- Screenshot capabilities
- CLI arguments for dynamic configuration
- Environment-specific settings
- Credential management
- Singleton pattern for global config access
- Dual output: Console and file logging
- Structured log format with timestamps
- Step-level logging
- Assertion logging with pass/fail status
- Separate log files per day
- Python 3.8 or higher
- pip (Python package manager)
- Clone the repository
cd playwright_test_fw- Create a virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate- Install dependencies
pip install -r requirements.txt- Install Playwright browsers
playwright install- Configure environment variables
cp .env.example .env
# Edit .env with your configurationpytest --env=qa --browser=chromium --headed --slowmo=500Available arguments:
--env: Environment (dev, qa, staging, prod) - Default: qa--browser: Browser (chromium, firefox, webkit) - Default: chromium--headed: Run in headed mode - Default: headless--slowmo: Slow down execution (ms) - Default: 0--base-url: Base URL override--timeout: Default timeout (ms) - Default: 30000
ENV=qa
BROWSER=chromium
HEADED=false
SLOWMO=0
TIMEOUT=30000
QA_URL=https://qa.example.com
DEFAULT_USERNAME=test@example.com
DEFAULT_PASSWORD=Test@123Run all tests:
pytestRun specific test file:
pytest tests/test_login.pyRun specific test:
pytest tests/test_login.py::TestLogin::test_login_with_valid_credentialsRun tests with markers:
pytest -m smoke # Run smoke tests
pytest -m login # Run login tests
pytest -m "smoke and login" # Run tests with both markersRun tests in parallel:
pytest -n 4 # Run with 4 workersRun with specific environment:
pytest --env=staging --browser=firefox --headedHTML Report:
pytest --html=reports/report.html --self-contained-htmlAllure Report:
pytest --alluredir=reports/allure-results
allure serve reports/allure-resultsimport pytest
from playwright.sync_api import Page
from steps.login_steps import LoginSteps
class TestLogin:
@pytest.mark.smoke
def test_login_success(self, page: Page, login_steps: LoginSteps):
# Navigate and verify page
login_steps.navigate_to_login_page()
login_steps.login_page.verify_login_page_loaded()
# Perform login
login_steps.login_with_valid_credentials()
# Verify success
login_steps.verify_login_successful()from pages.base_page import BasePage
class MyPage(BasePage):
def __init__(self, page):
super().__init__(page)
# Define locators
self.submit_button = "button[type='submit']"
self.input_field = "input#myfield"
def submit_form(self):
self.logger.info("Submitting form")
self.click(self.submit_button)from pages.my_page import MyPage
from utils.logger import Logger
class MySteps:
def __init__(self, page):
self.page = page
self.my_page = MyPage(page)
self.logger = Logger.get_logger(__name__)
def complete_workflow(self):
Logger.log_step(self.logger, "Complete workflow")
self.my_page.fill(self.my_page.input_field, "test")
self.my_page.submit_form()-
Separation of Concerns
- Keep tests simple and readable
- Business logic goes in steps
- UI interactions go in pages
-
Naming Conventions
- Tests:
test_<scenario_name> - Pages:
<page_name>_page.py - Steps:
<feature_name>_steps.py
- Tests:
-
Locator Strategy
- Prefer user-facing attributes (role, text, label)
- Use data-testid for dynamic content
- Avoid XPath unless necessary
-
Assertions
- Use built-in assertion methods from BasePage
- Add meaningful assertion messages
- Verify one thing per assertion
-
Logging
- Use Logger.log_step() for major steps
- Log important actions and verifications
- Include context in log messages
-
Screenshots
- Automatic screenshots on failure
- Manual screenshots for debugging
- Stored in screenshots/ directory
Issue: Tests failing with timeout
pytest --timeout=60000 # Increase timeout to 60 secondsIssue: Browser not found
playwright install chromiumIssue: Logs not generated
- Check
logs/directory permissions - Verify pytest.ini log configuration
Issue: Screenshots not saved
- Check
screenshots/directory exists - Verify conftest.py fixture configuration
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt
playwright install --with-deps
- name: Run tests
run: pytest --env=qa
- uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: |
reports/
screenshots/
logs/- Follow the existing code structure
- Add tests for new features
- Update documentation
- Follow PEP 8 style guidelines
- Add meaningful commit messages
This framework is provided as-is for educational and testing purposes.
For issues and questions:
- Check the documentation
- Review example tests
- Check logs for detailed error messages