A clean, modern test automation framework specifically designed for testing DemoQA.com built with Playwright, Python, and pytest. This framework demonstrates industry best practices for UI and API test automation with a simple, maintainable architecture.
This framework provides a complete example of how to structure a professional test automation project with proper separation of concerns, modern tooling, and environment-aware configuration.
Target Application: DemoQA.com - Practice website for test automation
Technology Stack: Python 3.8+ • Playwright • pytest • JSONPlaceholder API
Architecture: 4-layer clean architecture (Core, Services, Business, Tests)
- ✅ Chrome-Only UI Testing: Focused, reliable browser testing with Playwright
- ✅ Chrome DevTools Protocol (CDP): Support for distributed testing via CDP connection
- ✅ API Business Layer: Proper business objects for JSONPlaceholder API testing
- ✅ Environment-Aware Config: YAML-based configuration with environment overrides
- ✅ Jenkins Integration: Ready for parallel execution in CI/CD pipelines
- ✅ Clean Architecture: Simplified 4-layer structure with clear separation of concerns
- ✅ Playwright: Fast, reliable browser automation
- ✅ pytest: Advanced testing framework with parallel execution
- ✅ Environment Variables: Simple configuration management
- ✅ Docker Support: Chrome container for Jenkins parallel execution
- ✅ Type Hints: Full type safety throughout the codebase
python-taf-template/
├── 📄 README.md # Project documentation (this file)
├── 📄 CLAUDE.md # Development history and user instructions
├── 📄 requirements.txt # Python dependencies
├── 📄 pytest.ini # pytest configuration with cache management
├── 📄 pyproject.toml # Python project metadata
├── 📄 conftest.py # pytest fixtures and session configuration
├── 📄 docker-compose-jenkins.yml # Chrome container for Jenkins CI
├── 📄 Jenkinsfile # Jenkins pipeline configuration
├── 📄 test_cdp_connection.py # Chrome CDP connection testing utility
│
├── 📂 config/ # Configuration files
│ └── 📄 environments.yaml # Multi-environment configuration (local/dev/staging/prod)
│
├── 📂 scripts/ # Utility scripts
│ └── 📄 run_tests.py # Test execution helper script
│
├── 📂 framework/ # Core framework code
│ ├── 📂 core/ # Foundation layer
│ │ ├── 📄 config.py # Simple YAML→env var configuration loader
│ │ ├── 📄 base_test.py # Base test classes (BaseUITest, BaseAPITest)
│ │ ├── 📄 constants.py # Framework constants and enums
│ │ └── 📄 exceptions.py # Custom framework exceptions
│ │
│ ├── 📂 services/ # Services layer
│ │ ├── 📄 playwright_service.py # Playwright browser management with CDP support
│ │ ├── 📄 api_client.py # HTTP client for API testing
│ │ ├── 📄 database_service.py # Database connection utilities
│ │ └── 📄 reporting_service.py # Test reporting and analytics
│ │
│ ├── 📂 utilities/ # Utilities layer
│ │ ├── 📄 logger.py # Logging configuration with environment awareness
│ │ ├── 📄 data_utils.py # Test data generation with Faker
│ │ ├── 📄 validation_utils.py # Custom assertion helpers
│ │ └── 📄 file_utils.py # File operations and screenshot management
│ │
│ └── 📂 business/ # Business logic layer
│ ├── 📄 data_builders.py # Fluent test data builders
│ ├── 📄 playwright_page_objects.py # Base Playwright page object classes
│ │
│ ├── 📂 api/ # API business objects
│ │ ├── 📄 base_api.py # Base API endpoint class with common operations
│ │ ├── 📄 api_manager.py # Centralized API manager (JSONPlaceholderAPI)
│ │ ├── 📄 posts_api.py # Posts endpoint business object
│ │ ├── 📄 users_api.py # Users endpoint business object
│ │ ├── 📄 comments_api.py # Comments endpoint business object
│ │ ├── 📄 todos_api.py # Todos endpoint business object
│ │ └── 📄 albums_api.py # Albums endpoint business object
│ │
│ └── 📂 pages/ # DemoQA page objects
│ ├── 📄 home_page.py # DemoQA homepage interactions
│ ├── 📄 elements_page.py # Elements section page
│ ├── 📄 textbox_page.py # Text Box page interactions
│ ├── 📄 checkbox_page.py # Checkbox page interactions
│ └── 📄 radiobutton_page.py # Radio Button page interactions
│
├── 📂 tests/ # Test files (only test logic)
│ ├── 📄 test_framework_unit.py # Framework component unit tests
│ ├── 📄 test_api_business_layer.py # API business layer tests (30 tests)
│ ├── 📄 test_api_jsonplaceholder.py # Direct API integration tests
│ ├── 📄 test_demoqa_textbox.py # DemoQA Text Box UI tests
│ ├── 📄 test_demoqa_checkbox.py # DemoQA Checkbox UI tests
│ └── 📄 test_demoqa_radiobutton.py # DemoQA Radio Button UI tests
│
├── 📂 test_data/ # Test data files
├── 📂 reports/ # Test execution reports
├── 📂 screenshots/ # Failure screenshots
├── 📂 videos/ # Test execution videos
└── 📂 logs/ # Application and test logs
config/environments.yaml
: Multi-environment configuration with inheritance (local inherits from default, dev/staging/prod override specific values)framework/core/config.py
: Simple config loader that flattens YAML into environment variables at startuppytest.ini
: pytest configuration with parallel execution, reporting, and__pycache__
managementconftest.py
: Global pytest fixtures, session hooks, and environment setup
framework/services/playwright_service.py
: Playwright wrapper with CDP support for distributed testingframework/services/api_client.py
: HTTP client with retry logic, authentication, and response handlingtest_cdp_connection.py
: Utility to test Chrome CDP connection for Jenkins setup
framework/business/api/
: Business objects for each JSONPlaceholder API endpoint (eliminates direct API calls in tests)framework/business/pages/
: DemoQA page objects split into separate files for maintainabilityframework/business/data_builders.py
: Fluent builders for test data creation
tests/test_framework_unit.py
: Framework component validation (5 tests)tests/test_api_business_layer.py
: API business layer testing (30 tests covering all endpoints)tests/test_demoqa_*.py
: UI tests with no setup_method (uses BaseDemoQAUITest)
docker-compose-jenkins.yml
: Chrome container for Jenkins parallel executionJenkinsfile
: Complete pipeline with parallel test execution, reporting, and notifications
- Python 3.8+
- Docker (for Jenkins/CI environments)
- Chrome browser (for local development)
# Clone repository
git clone <repository-url>
cd python-taf-template
# Create virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
The framework uses a simple, powerful configuration system:
- YAML Configuration (
config/environments.yaml
):
default: &default
logging:
level: INFO
browser:
implicit_wait: 10
explicit_wait: 30
headless: false
local:
<<: *default
environment: local
base_url: "https://demoqa.com"
api_base_url: "https://jsonplaceholder.typicode.com"
dev:
<<: *default
environment: dev
base_url: "https://dev.example.com"
browser:
headless: true
-
Automatic Environment Variable Loading:
- Framework loads YAML and sets environment variables automatically
- Environment variables override YAML values
- No complex config objects or hardcoded values
-
Environment Variable Usage:
import os
# Framework automatically loads from YAML
base_url = os.getenv("BASE_URL") # "https://demoqa.com"
headless = os.getenv("BROWSER_HEADLESS") # "false"
timeout = int(os.getenv("BROWSER_EXPLICIT_WAIT", "30"))
# All tests
pytest tests/ -v
# Specific test categories
pytest tests/test_framework_unit.py -v # Framework validation
pytest tests/test_api_business_layer.py -v # API business layer (30 tests)
pytest tests/test_demoqa_*.py -v # UI tests only
# Different environments
ENVIRONMENT=dev pytest tests/ -v
ENVIRONMENT=staging pytest tests/ -v
# Browser options (Chrome only)
BROWSER_HEADLESS=true pytest tests/test_demoqa_textbox.py -v
# Parallel execution
pytest tests/ -v -n auto # Auto-detect cores
pytest tests/ -v -n 4 # Specific worker count
# Start Chrome container
docker-compose -f docker-compose-jenkins.yml up -d
# Run tests with CDP connection
CHROME_CDP_URL=http://localhost:9222 pytest tests/ -v -n 20
# Different environments
ENVIRONMENT=staging CHROME_CDP_URL=http://localhost:9222 pytest tests/ -v
class TestDemoQATextBox(BaseDemoQAUITest):
"""DemoQA Text Box tests - no setup_method needed."""
def test_fill_text_box_form(self):
# Navigate using explicit pattern
self.home_page.navigate_to_elements()
self.elements_page.navigate_to_textbox()
# Use business layer
test_data = user().with_email("[email protected]").build()
# Page object interactions
self.textbox_page.fill_all_fields(**test_data)
self.textbox_page.submit_form()
# Clean assertions
assert_helper.assert_text_visible(test_data["name"])
class TestAPIBusinessLayer:
"""Tests using API business objects - no direct API calls."""
def test_get_user_posts(self):
# Use business layer instead of direct API calls
api = JSONPlaceholderAPI()
# Business method with client-side filtering
posts_response = api.posts.get_posts_by_user(user_id=1)
# Business-level assertions
assert posts_response.status_code == 200
assert len(posts_response.data) > 0
- All configuration comes from
environments.yaml
- Environment variables override YAML values
- No hardcoded URLs, timeouts, or credentials
- API Tests: Use business objects (
api.posts.get_by_user(1)
) instead of raw HTTP calls - UI Tests: Use page objects with explicit navigation patterns
- Test Data: Use fluent builders for data creation
- Tests contain only test logic - no setup, no page interactions
- BaseDemoQAUITest handles all page object initialization
- Explicit navigation -
self.home_page.navigate_to_elements()
instead of hidden setup
- Multi-environment support: local, dev, staging, prod
- Deep inheritance: Dev environment inherits default settings, overrides specific ones
- No environment-specific code: Same tests run across all environments
- Create page object in
framework/business/pages/new_page.py
- Add to BaseDemoQAUITest initialization in
framework/core/base_test.py
- Write tests in
tests/test_demoqa_newfeature.py
- Follow explicit navigation pattern:
self.home_page.navigate_to_xyz()
- Create business object in
framework/business/api/new_api.py
- Extend BaseAPIEndpoint with endpoint-specific methods
- Add to APIManager in
framework/business/api/api_manager.py
- Write business layer tests in
tests/test_api_business_layer.py
- Add environment section to
config/environments.yaml
- Override necessary values (URLs, settings)
- Use inheritance - extend default configuration
- Test with:
ENVIRONMENT=newenv pytest tests/
- ✅ Parallel Execution: Multiple workers per Jenkins node
- ✅ Chrome Container: Isolated browser via Docker Compose
- ✅ Environment Parameters: Choose environment, test suite, parallel workers
- ✅ Comprehensive Reporting: HTML, Allure, JUnit XML, JSON reports
- ✅ Artifact Management: Screenshots, logs, reports archived
- ✅ Smart Cleanup: Configurable workspace cleanup
// Jenkinsfile provides
parameters {
choice(name: 'ENVIRONMENT', choices: ['local', 'dev', 'staging', 'prod'])
choice(name: 'TEST_SUITE', choices: ['all', 'smoke', 'regression', 'api', 'ui'])
string(name: 'PARALLEL_WORKERS', defaultValue: 'auto')
}
// Automatic Chrome setup
stage('Chrome Container Setup') {
steps {
sh 'docker-compose -f docker-compose-jenkins.yml up -d playwright-chrome'
sh 'curl -f http://localhost:9222/json/version' // Verify connection
}
}
- HTML Reports: Self-contained reports with embedded screenshots
- JSON Reports: Machine-readable test results for analytics
- JUnit XML: Standard format for CI/CD integration
- Allure Reports: Rich interactive reports with history
- Screenshots: Automatic capture on failures with timestamps
- Environment-aware: Different log levels per environment
- Structured logging: JSON format for log aggregation
- Test correlation: Each test run has unique correlation ID
- Performance metrics: Test duration and resource usage tracking
Configuration Problems:
# Test configuration loading
python -c "from framework.core.config import load_config; import os; print(f'Base URL: {os.getenv(\"BASE_URL\")}')"
Chrome CDP Connection:
# Test CDP connection
python test_cdp_connection.py
# Manual verification
curl http://localhost:9222/json/version
Test Failures:
- Check
screenshots/
directory for failure screenshots - Review
logs/
directory for detailed execution logs - Use
pytest -v -s
for verbose output with print statements
- Parallel Execution: Use
-n auto
for optimal worker count - Headless Mode: Set
BROWSER_HEADLESS=true
for faster execution - CDP Connection: Use remote Chrome for distributed testing
- Cache Management: Framework automatically manages
__pycache__
in temp directory
This framework has evolved through several major iterations:
- Initial Setup: Basic Selenium-based framework
- Business Layer: Added API business objects (eliminated direct API calls)
- UI Refactoring: Removed repetitive setup_method, added BaseDemoQAUITest
- Page Organization: Split monolithic page objects into separate files
- Browser Modernization: Migrated from Selenium to Playwright with CDP
- Configuration Simplification: Replaced complex config classes with simple YAML→env vars
- Architecture Cleanup: Removed unnecessary Docker files, updated CI/CD pipeline
See CLAUDE.md
for detailed development history and accomplishments.
Framework Version: 3.0
Target Application: https://demoqa.com | https://jsonplaceholder.typicode.com
Technology Stack: Python 3.8+ • Playwright • pytest • Docker
Last Updated: July 2025
Architecture: Clean 4-layer architecture with business layer pattern