Enterprise-grade test automation framework featuring native W3C WebDriver BiDi accessibility locators with intelligent fallback strategies
This framework revolutionizes Selenium automation by providing native accessibility-based element location that mirrors how users actually interact with web applications. It seamlessly integrates W3C WebDriver BiDi protocol with intelligent fallback mechanisms for maximum compatibility and future-proofing.
- π― W3C BiDi Native Support: First-class implementation of
browsingContext.locateNodes - π Natural ARIA Locators: Find elements by roles and accessible names
- π§ Zero-Setup Installation: Auto-extends WebDriver with new methods
- π Intelligent Fallback: BiDi β CDP β DOM cascade for 100% compatibility
- ποΈ Enterprise Architecture: Production-ready with comprehensive error handling
- π Performance Optimized: Caching and strategy pattern implementation
- π Quick Start
- ποΈ Architecture Overview
- π BiDi Accessibility Locators
- βοΈ Implementation Details
- π§ͺ Testing & Debugging
- π Command Reference
- π Browser Support
- π Project Structure
- π§ Advanced Usage
# Clone repository git clone <repository-url> cd python-se # Create virtual environment (recommended) python -m venv se-python-env source se-python-env/bin/activate # Windows: se-python-env\Scripts\activate # Install dependencies pip install -r requirements.txtimport utils # π Auto-enables ARIA methods on WebDriver! # Natural element location (just like native Selenium) username = driver.find_element_by_role("textbox", name="Username") submit_btn = driver.find_element_by_role("button", name="Submit") all_links = driver.find_elements_by_role("link")from utils import ARIARole, LocatorConfig # Use enums for IDE support and safety email_field = driver.find_element_by_role(ARIARole.TEXTBOX, name="Email") login_button = driver.find_element_by_role(ARIARole.BUTTON, name="Login") # Configure advanced options config = LocatorConfig( bidi_priority=True, # Prefer BiDi when available cdp_fallback=True, # Enable CDP fallback debug_mode=True # Detailed logging )Our framework implements a sophisticated cascading fallback system:
graph TD A[ARIA Locator Request] --> B{BiDi Available?} B -->|Yes| C[W3C BiDi browsingContext.locateNodes] B -->|No| D{CDP Available?} D -->|Yes| E[Chrome DevTools Protocol] D -->|No| F[DOM CSS Selectors + Accessibility Tree] C --> G{Elements Found?} E --> G F --> G G -->|Yes| H[Return WebElements] G -->|No| I[Graceful Fallback/Exception] | Component | Purpose | Technology |
|---|---|---|
| BiDiAccessibilityLocator | W3C BiDi native implementation | browsingContext.locateNodes |
| CDPAccessibilityBridge | Chrome DevTools fallback | Accessibility.getFullAXTree |
| DOMAccessibilityParser | Universal DOM fallback | CSS selectors + ARIA parsing |
| WebDriverExtensions | Seamless API integration | Dynamic method injection |
- Intelligent Caching: Context IDs and availability checks
- Strategy Pattern: Modular execution methods
- Lazy Loading: Components initialized on-demand
- Error Chaining: Comprehensive debugging information
WebDriver BiDi (Bidirectional Protocol) is the next-generation W3C standard that enables two-way communication between test scripts and browsers. Our framework leverages BiDi's browsingContext.locateNodes command for native accessibility-based element location.
- π― Native Performance: Direct browser communication
- π‘οΈ Future-Proof: W3C standard implementation
- π True Accessibility: Authentic accessibility tree traversal
- π Cross-Browser: Consistent behavior across all browsers
from utils.bidi_locators import BiDiAccessibilityLocator # Direct BiDi usage locator = BiDiAccessibilityLocator(driver) # Check BiDi availability if locator.is_available(): elements = locator.find_elements( role="button", name="Submit", max_count=10 )# Enable BiDi in your WebDriver chrome_options.set_capability("webSocketUrl", True) # Essential! firefox_options.set_capability("webSocketUrl", True) edge_options.set_capability("webSocketUrl", True)| Role | Description | Additional Attributes |
|---|---|---|
textbox | Input fields, textareas | placeholder, required |
button | Buttons, submit elements | pressed, disabled |
checkbox | Checkbox inputs | checked, disabled |
radio | Radio button inputs | checked, disabled |
link | Anchor elements | href |
heading | Headers (h1-h6) | level |
listitem | List items | setsize, posinset |
tab | Tab elements | selected |
dialog | Modal dialogs | modal |
class BiDiAccessibilityLocator: def _execute_bidi_command(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]: execution_strategies = [ self._try_native_browsing_context, # Selenium 4.15+ self._try_direct_bidi_command, # Future versions self._try_legacy_bidi_connection, # Legacy support self._try_cdp_bridge # CDP fallback ] for strategy in execution_strategies: try: result = strategy(method, params) if result is not None: return result except Exception as e: logger.debug(f"Strategy failed: {strategy.__name__}: {e}") continueclass BiDiAccessibilityLocator: def __init__(self, driver: WebDriver) -> None: self.driver = driver self._context_id: Optional[str] = None # Cache context ID self._bidi_available: Optional[bool] = None # Cache availability# Exception chaining for better debugging except WebDriverException as e: raise BiDiNotAvailableError(f"Context error: {e}") from e-
BiDi Native (
_try_native_browsing_context):driver.browsing_context.locate_nodes( context=context_id, locator={"type": "accessibility", "value": {"role": "button"}}, max_node_count=1000 )
-
CDP Bridge (
_try_cdp_bridge):driver.execute_cdp_cmd("Accessibility.enable", {}) tree_result = driver.execute_cdp_cmd("Accessibility.getFullAXTree", {})
-
DOM Fallback:
driver.find_elements(By.CSS_SELECTOR, 'button, [role="button"]')
Our comprehensive test suite validates all implementation layers:
class TestBiDiIntegration: def test_bidi_availability_check(self, driver): """Verify BiDi detection works correctly""" def test_bidi_direct_usage_when_available(self, driver): """Test direct BiDi implementation""" def test_priority_order_works(self, driver): """Verify BiDi β CDP β DOM cascade""" def test_error_handling(self, driver): """Test robust error scenarios"""Enable detailed logging to understand execution flow:
from utils import LocatorConfig config = LocatorConfig(debug_mode=True)Debug Output Example:
DEBUG Using native BiDi accessibility locators DEBUG -> {"method": "browsingContext.locateNodes", "params": {...}} DEBUG <- {'id': 1, 'result': {'nodes': []}, 'type': 'success'} DEBUG BiDi accessibility found 0 elements DEBUG CDP accessibility tree found 2 elements DEBUG DOM search found 2 elements def test_performance_comparison(self, driver): """Compare BiDi vs CDP vs DOM performance""" # Measure execution times bidi_time = measure_execution_time(bidi_locator.find_elements) cdp_time = measure_execution_time(cdp_locator.find_elements) dom_time = measure_execution_time(dom_locator.find_elements)# Run all tests (default: Chrome) pytest tests/ -v # Test specific browser pytest tests/ --browser chrome -v pytest tests/ --browser firefox -v pytest tests/ --browser edge -v # Run specific test file pytest tests/test_bidi_integration.py -v pytest tests/test_get_by_role.py -v# Test BiDi functionality across all browsers pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=chrome -v pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=firefox -v pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=edge -v # Test priority system (BiDi β CDP β DOM) pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_priority_order_works -v # Test with debug logging pytest tests/test_bidi_integration.py -v -s --log-cli-level=DEBUG# Enable verbose debug output pytest tests/ -v -s --log-cli-level=DEBUG # Run single test with maximum verbosity pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_locator_config_debug_mode -v -s --log-cli-level=DEBUG # Generate HTML test report pytest tests/ --html=report.html --self-contained-html # Run tests and show performance metrics pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_performance_comparison -v -s# Install in development mode pip install -e . # Run linting (if configured) flake8 utils/ tests/ # Type checking (if configured) mypy utils/ # Run tests with coverage pytest tests/ --cov=utils --cov-report=html# Test BiDi availability detection python -c " from selenium import webdriver from utils.bidi_locators import is_bidi_accessibility_available from selenium.webdriver.chrome.options import Options options = Options() options.set_capability('webSocketUrl', True) driver = webdriver.Chrome(options=options) print(f'BiDi Available: {is_bidi_accessibility_available(driver)}') driver.quit() " # Test error handling scenarios python -c " from selenium import webdriver from utils.bidi_locators import BiDiAccessibilityLocator, BiDiNotAvailableError driver = webdriver.Chrome() # No webSocketUrl locator = BiDiAccessibilityLocator(driver) try: locator.find_element('button') except BiDiNotAvailableError as e: print(f'Expected error: {e}') driver.quit() " # Manual BiDi testing python -c " from selenium import webdriver from selenium.webdriver.chrome.options import Options from utils.bidi_locators import BiDiAccessibilityLocator options = Options() options.set_capability('webSocketUrl', True) driver = webdriver.Chrome(options=options) driver.get('https://example.com') locator = BiDiAccessibilityLocator(driver) print(f'BiDi Available: {locator.is_available()}') # Try direct BiDi usage try: elements = locator.find_elements('button') print(f'Found {len(elements)} buttons via BiDi') except Exception as e: print(f'BiDi error: {e}') driver.quit() "| Browser | BiDi Native | CDP Fallback | DOM Fallback | Status |
|---|---|---|---|---|
| Chrome 118+ | β | β | β | Fully Supported |
| Firefox 119+ | β | β | β | Fully Supported |
| Edge 118+ | β | β | β | Fully Supported |
| Safari | β³ | β | β | DOM Only |
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.set_capability("webSocketUrl", True) # Enable BiDi chrome_options.add_argument("--headless") # Optional chrome_options.add_argument("--no-sandbox") # CI/CD chrome_options.add_argument("--disable-dev-shm-usage") driver = webdriver.Chrome(options=chrome_options)from selenium.webdriver.firefox.options import Options firefox_options = Options() firefox_options.set_capability("webSocketUrl", True) # Enable BiDi firefox_options.add_argument("--headless") # Optional driver = webdriver.Firefox(options=firefox_options)from selenium.webdriver.edge.options import Options edge_options = Options() edge_options.set_capability("webSocketUrl", True) # Enable BiDi edge_options.add_argument("--headless") # Optional driver = webdriver.Edge(options=edge_options)python-se/ βββ π tests/ # Test suite β βββ conftest.py # pytest configuration & fixtures β βββ test_bidi_integration.py # π― BiDi integration tests β βββ test_get_by_role.py # ARIA locator tests β βββ test_login_page.py # Example test scenarios βββ π utils/ # Core framework β βββ __init__.py # Package initialization β βββ aria_locators.py # π Main ARIA implementation β βββ bidi_locators.py # π W3C BiDi implementation β βββ webdriver_extensions.py # WebDriver method injection βββ π requirements.txt # Python dependencies βββ π readme.md # This documentation βββ π BLOG_POST.md # Technical blog post βββ π SELENIUM_ISSUE_UPDATE.md # BiDi implementation notes BiDiAccessibilityLocator: Main BiDi locator class- Strategy pattern for execution methods
- Intelligent caching and error handling
- Full W3C
browsingContext.locateNodessupport
- Multi-tier locator strategy (BiDi β CDP β DOM)
- ARIARole enum definitions
- LocatorConfig for advanced options
- Performance optimization
- Dynamic method injection into WebDriver
find_element_by_role()/find_elements_by_role()- Zero-setup auto-installation
- BiDi availability testing
- Cross-browser compatibility validation
- Priority system verification
- Performance benchmarking
from utils import LocatorConfig # Advanced configuration config = LocatorConfig( bidi_priority=True, # Prefer BiDi when available cdp_fallback=True, # Enable CDP fallback dom_fallback=True, # Enable DOM fallback debug_mode=True, # Detailed logging timeout=10, # Element timeout (seconds) retry_count=3, # Retry attempts cache_results=True # Cache element lookups ) # Apply configuration globally driver.aria_config = configfrom utils.bidi_locators import BiDiAccessibilityLocator # Direct BiDi usage (advanced) bidi_locator = BiDiAccessibilityLocator(driver) if bidi_locator.is_available(): # Find with custom parameters elements = bidi_locator.find_elements( role="button", name="Submit", max_count=5, # Limit results pressed=False, # Button state disabled=False # Accessibility state ) # Single element with validation try: submit_btn = bidi_locator.find_element("button", name="Submit") except NoSuchElementException: print("Submit button not found")import time from utils import LocatorConfig # Performance testing config = LocatorConfig(debug_mode=True) start_time = time.time() elements = driver.find_elements_by_role("button") execution_time = time.time() - start_time print(f"Found {len(elements)} elements in {execution_time:.3f}s")from utils.bidi_locators import BiDiNotAvailableError from selenium.common.exceptions import NoSuchElementException try: # Attempt element location element = driver.find_element_by_role("button", name="Submit") element.click() except BiDiNotAvailableError: # BiDi not available, but fallback should work print("BiDi unavailable, using fallback methods") except NoSuchElementException: # Element genuinely not found print("Submit button not found on page") except Exception as e: # Unexpected error print(f"Unexpected error: {e}")We welcome contributions! This framework represents cutting-edge Selenium automation with W3C BiDi integration.
git clone <repository-url> cd python-se python -m venv dev-env source dev-env/bin/activate pip install -r requirements.txt pip install -e .# Full test suite pytest tests/ -v # BiDi-specific tests pytest tests/test_bidi_integration.py -v # With coverage pytest tests/ --cov=utils --cov-report=htmlMIT License - Feel free to use in your projects!
- W3C BiDi Native: First framework with production-ready BiDi accessibility locators
- Future-Proof: Built on emerging W3C standards
- Enterprise-Ready: Production-tested architecture patterns
- Zero Setup: Import and use immediately
- Natural API: Familiar Selenium-style methods
- Type Safety: Full IDE support with enums
- Comprehensive Docs: Extensive documentation and examples
- Intelligent Fallbacks: Never fails due to technology limitations
- Cross-Browser: Consistent behavior across all major browsers
- Performance Optimized: Caching and strategy patterns
- Error Resilient: Comprehensive error handling and debugging
| Aspect | Traditional Selenium | This Framework |
|---|---|---|
| Locator Strategy | CSS/XPath selectors | Accessibility-based |
| Brittleness | High (layout changes break) | Low (semantic stability) |
| Readability | Poor (By.XPATH, "//div[@class='btn']") | Excellent (role="button") |
| Future-Proof | No (legacy selectors) | Yes (W3C standards) |
| Performance | Variable | Optimized with caching |
| Browser Support | Manual configuration | Auto-detection + fallbacks |
π― Ready to revolutionize your Selenium automation? Get started with W3C BiDi accessibility locators today!