--- description: Selenium + pytest framework architecture — configuration, fixtures, and dependency management globs: **/conftest.py,**/pytest.ini,**/requirements.txt,**/pyproject.toml alwaysApply: false --- # Selenium Python Framework Architecture ## Modern Framework Foundation - **pytest Framework**: Leverage pytest's powerful fixture system and plugin ecosystem - **Modular Architecture**: Separate concerns with clear package structure - **Configuration Management**: Environment-specific settings with proper inheritance - **Dependency Management**: Pinned versions with regular security updates ## Project Structure Best Practices ``` selenium-project/ ├── tests/ │ ├── conftest.py # Global pytest configuration │ ├── pages/ # Page Object Models │ ├── specs/ # Test specifications │ ├── utils/ # Helper utilities │ └── data/ # Test data files ├── config/ │ ├── environments/ # Environment configurations │ └── browsers/ # Browser configurations ├── reports/ # Test execution reports ├── logs/ # Application logs ├── requirements.txt # Python dependencies └── pytest.ini # pytest configuration ``` ## pytest Configuration Excellence ```python # conftest.py - Global configuration import pytest import os from selenium import webdriver from selenium.webdriver.chrome.options import Options as ChromeOptions from webdriver_manager.chrome import ChromeDriverManager def pytest_addoption(parser): """Command line options for flexible test execution.""" parser.addoption("--browser", action="store", default="chrome") parser.addoption("--headless", action="store_true", default=False) parser.addoption("--env", action="store", default="dev") parser.addoption("--parallel", action="store", default="1") @pytest.fixture(scope="session") def browser_config(request): """Browser configuration based on command line arguments.""" return { "browser": request.config.getoption("--browser"), "headless": request.config.getoption("--headless"), "environment": request.config.getoption("--env") } ``` ## Environment Management ```python # Environment-specific configuration loading import yaml import os from typing import Dict, Any class ConfigManager: """Centralized configuration management.""" def __init__(self, environment: str = "dev"): self.environment = environment self.config = self._load_config() def _load_config(self) -> Dict[str, Any]: """Load environment-specific configuration.""" config_file = f"config/environments/{self.environment}.yaml" if not os.path.exists(config_file): raise FileNotFoundError(f"Configuration file not found: {config_file}") with open(config_file, 'r') as f: config = yaml.safe_load(f) # Validate required keys required_keys = ["base_url", "timeouts", "credentials"] for key in required_keys: if key not in config: raise KeyError(f"Missing required configuration: {key}") return config def get(self, key: str, default=None): """Get configuration value with dot notation support.""" keys = key.split('.') value = self.config for k in keys: if isinstance(value, dict) and k in value: value = value[k] else: return default return value ``` ## Dependency Management ```ini # requirements.txt - Pinned versions for stability selenium==4.15.0 pytest==7.4.0 pytest-html==4.1.1 pytest-xdist==3.3.1 webdriver-manager==4.0.1 pyyaml==6.0.1 allure-pytest==2.13.2 python-dotenv==1.0.0 # Development dependencies black==23.9.1 flake8==6.1.0 mypy==1.6.0 ```