fagun-browser-testing / src /utils /enhanced_ai_testing.py
fagun18's picture
Upload folder using huggingface_hub
2b89d68 verified
raw
history blame
27.5 kB
"""
🤖 Fagun Browser Automation Testing Agent - Enhanced AI Testing Engine
====================================================================
Enhanced AI testing engine that aggressively finds errors, bugs, and issues
with comprehensive test scenarios and intelligent bug detection.
Author: Mejbaur Bahar Fagun
Role: Software Engineer in Test
LinkedIn: https://www.linkedin.com/in/mejbaur/
"""
import asyncio
import random
import string
from typing import List, Dict, Any, Optional
from playwright.async_api import Page, Locator
import logging
from dataclasses import dataclass
from enum import Enum
logger = logging.getLogger(__name__)
class BugSeverity(Enum):
"""Bug severity levels."""
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFO = "info"
@dataclass
class BugReport:
"""Bug report structure."""
title: str
severity: BugSeverity
description: str
steps_to_reproduce: List[str]
expected_behavior: str
actual_behavior: str
url: str
element_info: Dict[str, Any]
recommendations: List[str]
class EnhancedAITestingEngine:
"""Enhanced AI testing engine with aggressive bug finding capabilities."""
def __init__(self):
self.bugs_found: List[BugReport] = []
self.test_scenarios = self._load_test_scenarios()
self.bug_patterns = self._load_bug_patterns()
self.performance_thresholds = self._load_performance_thresholds()
def _load_test_scenarios(self) -> Dict[str, List[Dict[str, Any]]]:
"""Load comprehensive test scenarios."""
return {
"navigation": [
{"action": "rapid_navigation", "description": "Rapidly navigate between pages"},
{"action": "back_forward", "description": "Test browser back/forward buttons"},
{"action": "refresh_test", "description": "Test page refresh functionality"},
{"action": "url_manipulation", "description": "Test URL manipulation and direct access"}
],
"form_testing": [
{"action": "empty_submission", "description": "Submit forms with empty fields"},
{"action": "invalid_data", "description": "Submit forms with invalid data"},
{"action": "sql_injection", "description": "Test for SQL injection vulnerabilities"},
{"action": "xss_attempts", "description": "Test for XSS vulnerabilities"},
{"action": "large_data", "description": "Submit forms with large amounts of data"},
{"action": "special_characters", "description": "Test with special characters"},
{"action": "unicode_testing", "description": "Test with Unicode characters"},
{"action": "script_injection", "description": "Test for script injection"}
],
"ui_testing": [
{"action": "responsive_test", "description": "Test responsive design"},
{"action": "accessibility_test", "description": "Test accessibility features"},
{"action": "hover_effects", "description": "Test hover effects and interactions"},
{"action": "click_areas", "description": "Test clickable areas and buttons"},
{"action": "scroll_behavior", "description": "Test scrolling behavior"},
{"action": "zoom_testing", "description": "Test zoom functionality"},
{"action": "keyboard_navigation", "description": "Test keyboard navigation"}
],
"performance": [
{"action": "load_time_test", "description": "Test page load times"},
{"action": "resource_loading", "description": "Test resource loading performance"},
{"action": "memory_usage", "description": "Monitor memory usage"},
{"action": "cpu_usage", "description": "Monitor CPU usage"},
{"action": "network_latency", "description": "Test network latency"}
],
"security": [
{"action": "csrf_test", "description": "Test for CSRF vulnerabilities"},
{"action": "clickjacking", "description": "Test for clickjacking vulnerabilities"},
{"action": "session_management", "description": "Test session management"},
{"action": "authentication", "description": "Test authentication mechanisms"},
{"action": "authorization", "description": "Test authorization controls"}
]
}
def _load_bug_patterns(self) -> Dict[str, List[str]]:
"""Load bug detection patterns."""
return {
"ui_bugs": [
"Element not visible",
"Element not clickable",
"Layout broken",
"Text overflow",
"Image not loading",
"Button not responding",
"Form validation missing",
"Error message not displayed",
"Loading state not handled",
"Responsive design issues"
],
"functional_bugs": [
"Function not working",
"Data not saved",
"Validation bypassed",
"Error not handled",
"State not maintained",
"Navigation broken",
"Search not working",
"Filter not applied",
"Sort not working",
"Pagination broken"
],
"performance_bugs": [
"Page load too slow",
"Memory leak detected",
"CPU usage high",
"Network timeout",
"Resource not optimized",
"Caching issues",
"Database slow query",
"API response slow",
"Image not optimized",
"JavaScript blocking"
],
"security_bugs": [
"SQL injection possible",
"XSS vulnerability",
"CSRF token missing",
"Authentication bypass",
"Authorization issue",
"Data exposure",
"Session hijacking",
"Clickjacking possible",
"Input not sanitized",
"Error information leaked"
]
}
def _load_performance_thresholds(self) -> Dict[str, float]:
"""Load performance thresholds."""
return {
"page_load_time": 3.0, # seconds
"element_interaction_time": 1.0, # seconds
"form_submission_time": 2.0, # seconds
"navigation_time": 1.5, # seconds
"memory_usage_mb": 100.0, # MB
"cpu_usage_percent": 80.0, # percentage
}
async def run_comprehensive_testing(self, page: Page) -> List[BugReport]:
"""Run comprehensive testing with all AI agents."""
logger.info("🤖 Starting comprehensive AI testing...")
# Clear previous bugs
self.bugs_found.clear()
# Run all test scenarios
await self._test_navigation_scenarios(page)
await self._test_form_scenarios(page)
await self._test_ui_scenarios(page)
await self._test_performance_scenarios(page)
await self._test_security_scenarios(page)
logger.info(f"🔍 Found {len(self.bugs_found)} bugs/issues during testing")
return self.bugs_found
async def _test_navigation_scenarios(self, page: Page):
"""Test navigation scenarios."""
logger.info("🧭 Testing navigation scenarios...")
try:
# Test rapid navigation
await self._rapid_navigation_test(page)
# Test back/forward
await self._back_forward_test(page)
# Test refresh
await self._refresh_test(page)
# Test URL manipulation
await self._url_manipulation_test(page)
except Exception as e:
logger.error(f"Navigation testing error: {e}")
async def _test_form_scenarios(self, page: Page):
"""Test form scenarios."""
logger.info("📝 Testing form scenarios...")
try:
# Find all forms
forms = await page.query_selector_all('form')
for form in forms:
# Test empty submission
await self._test_empty_form_submission(form, page)
# Test invalid data
await self._test_invalid_form_data(form, page)
# Test SQL injection
await self._test_sql_injection_forms(form, page)
# Test XSS attempts
await self._test_xss_forms(form, page)
# Test large data
await self._test_large_form_data(form, page)
# Test special characters
await self._test_special_characters(form, page)
except Exception as e:
logger.error(f"Form testing error: {e}")
async def _test_ui_scenarios(self, page: Page):
"""Test UI scenarios."""
logger.info("🎨 Testing UI scenarios...")
try:
# Test responsive design
await self._test_responsive_design(page)
# Test accessibility
await self._test_accessibility(page)
# Test hover effects
await self._test_hover_effects(page)
# Test clickable areas
await self._test_clickable_areas(page)
# Test scrolling
await self._test_scrolling_behavior(page)
except Exception as e:
logger.error(f"UI testing error: {e}")
async def _test_performance_scenarios(self, page: Page):
"""Test performance scenarios."""
logger.info("⚡ Testing performance scenarios...")
try:
# Test page load time
await self._test_page_load_time(page)
# Test resource loading
await self._test_resource_loading(page)
# Test memory usage
await self._test_memory_usage(page)
# Test network performance
await self._test_network_performance(page)
except Exception as e:
logger.error(f"Performance testing error: {e}")
async def _test_security_scenarios(self, page: Page):
"""Test security scenarios."""
logger.info("🔒 Testing security scenarios...")
try:
# Test CSRF
await self._test_csrf_vulnerabilities(page)
# Test clickjacking
await self._test_clickjacking(page)
# Test session management
await self._test_session_management(page)
# Test authentication
await self._test_authentication(page)
except Exception as e:
logger.error(f"Security testing error: {e}")
async def _rapid_navigation_test(self, page: Page):
"""Test rapid navigation between pages."""
try:
# Get all links
links = await page.query_selector_all('a[href]')
if len(links) > 3:
# Click first 3 links rapidly
for i in range(min(3, len(links))):
try:
await links[i].click()
await page.wait_for_timeout(500) # Short wait
# Check for errors
if await self._check_for_errors(page):
self._add_bug_report(
title="Rapid Navigation Error",
severity=BugSeverity.MEDIUM,
description="Error occurred during rapid navigation",
steps_to_reproduce=["Navigate rapidly between pages", "Click multiple links quickly"],
expected_behavior="Navigation should work smoothly",
actual_behavior="Error occurred during navigation",
url=page.url,
element_info={"link_index": i},
recommendations=["Add loading states", "Implement proper error handling"]
)
except Exception as e:
self._add_bug_report(
title="Navigation Failure",
severity=BugSeverity.HIGH,
description=f"Failed to navigate: {str(e)}",
steps_to_reproduce=["Click on navigation link", "Observe error"],
expected_behavior="Navigation should work",
actual_behavior=f"Navigation failed: {str(e)}",
url=page.url,
element_info={"link_index": i},
recommendations=["Fix navigation logic", "Add error handling"]
)
except Exception as e:
logger.error(f"Rapid navigation test error: {e}")
async def _test_empty_form_submission(self, form: Locator, page: Page):
"""Test form submission with empty fields."""
try:
# Find all input fields
inputs = await form.query_selector_all('input, textarea, select')
if inputs:
# Try to submit empty form
submit_button = await form.query_selector('button[type="submit"], input[type="submit"]')
if submit_button:
await submit_button.click()
await page.wait_for_timeout(1000)
# Check if validation is working
error_elements = await page.query_selector_all('.error, .invalid, [class*="error"], [class*="invalid"]')
if not error_elements:
self._add_bug_report(
title="Missing Form Validation",
severity=BugSeverity.HIGH,
description="Form accepts empty submissions without validation",
steps_to_reproduce=["Leave form fields empty", "Submit form"],
expected_behavior="Form should show validation errors",
actual_behavior="Form submitted without validation",
url=page.url,
element_info={"form_action": await form.get_attribute("action")},
recommendations=["Add client-side validation", "Add server-side validation"]
)
except Exception as e:
logger.error(f"Empty form submission test error: {e}")
async def _test_sql_injection_forms(self, form: Locator, page: Page):
"""Test forms for SQL injection vulnerabilities."""
try:
inputs = await form.query_selector_all('input[type="text"], input[type="email"], textarea')
sql_payloads = [
"' OR '1'='1",
"'; DROP TABLE users; --",
"' UNION SELECT * FROM users --",
"admin'--",
"' OR 1=1#"
]
for input_field in inputs:
for payload in sql_payloads:
try:
await input_field.fill(payload)
submit_button = await form.query_selector('button[type="submit"], input[type="submit"]')
if submit_button:
await submit_button.click()
await page.wait_for_timeout(1000)
# Check for SQL error messages
content = await page.content()
sql_errors = [
"mysql_fetch_array", "ORA-01756", "Microsoft OLE DB Provider",
"SQLServer JDBC Driver", "PostgreSQL query failed", "Warning: mysql_",
"valid MySQL result", "MySqlClient.", "SQL syntax"
]
for error in sql_errors:
if error.lower() in content.lower():
self._add_bug_report(
title="SQL Injection Vulnerability",
severity=BugSeverity.CRITICAL,
description=f"SQL injection vulnerability detected with payload: {payload}",
steps_to_reproduce=[f"Enter payload: {payload}", "Submit form"],
expected_behavior="Input should be sanitized",
actual_behavior="SQL injection successful",
url=page.url,
element_info={"payload": payload, "error": error},
recommendations=["Use parameterized queries", "Sanitize input", "Implement proper validation"]
)
break
# Clear input for next test
await input_field.fill("")
except Exception as e:
logger.warning(f"SQL injection test error: {e}")
continue
except Exception as e:
logger.error(f"SQL injection form test error: {e}")
async def _test_xss_forms(self, form: Locator, page: Page):
"""Test forms for XSS vulnerabilities."""
try:
inputs = await form.query_selector_all('input[type="text"], input[type="email"], textarea')
xss_payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')",
"<svg onload=alert('XSS')>",
"<iframe src=javascript:alert('XSS')></iframe>"
]
for input_field in inputs:
for payload in xss_payloads:
try:
await input_field.fill(payload)
submit_button = await form.query_selector('button[type="submit"], input[type="submit"]')
if submit_button:
await submit_button.click()
await page.wait_for_timeout(1000)
# Check if payload is reflected
content = await page.content()
if payload in content:
self._add_bug_report(
title="XSS Vulnerability",
severity=BugSeverity.CRITICAL,
description=f"XSS vulnerability detected with payload: {payload}",
steps_to_reproduce=[f"Enter payload: {payload}", "Submit form"],
expected_behavior="Input should be sanitized",
actual_behavior="XSS payload reflected",
url=page.url,
element_info={"payload": payload},
recommendations=["Sanitize output", "Use CSP headers", "Validate input"]
)
# Clear input for next test
await input_field.fill("")
except Exception as e:
logger.warning(f"XSS test error: {e}")
continue
except Exception as e:
logger.error(f"XSS form test error: {e}")
async def _test_responsive_design(self, page: Page):
"""Test responsive design."""
try:
viewports = [
{"width": 320, "height": 568}, # iPhone SE
{"width": 375, "height": 667}, # iPhone 8
{"width": 768, "height": 1024}, # iPad
{"width": 1024, "height": 768}, # Desktop
{"width": 1920, "height": 1080} # Large desktop
]
for viewport in viewports:
await page.set_viewport_size(viewport)
await page.wait_for_timeout(500)
# Check for layout issues
elements = await page.query_selector_all('*')
for element in elements:
try:
box = await element.bounding_box()
if box and (box['width'] > viewport['width'] or box['height'] > viewport['height']):
self._add_bug_report(
title="Responsive Design Issue",
severity=BugSeverity.MEDIUM,
description=f"Element overflows viewport at {viewport['width']}x{viewport['height']}",
steps_to_reproduce=[f"Set viewport to {viewport['width']}x{viewport['height']}", "Check layout"],
expected_behavior="Elements should fit within viewport",
actual_behavior="Element overflows viewport",
url=page.url,
element_info={"viewport": viewport, "element_box": box},
recommendations=["Fix CSS media queries", "Adjust element sizing", "Test responsive design"]
)
except Exception as e:
continue
except Exception as e:
logger.error(f"Responsive design test error: {e}")
async def _test_page_load_time(self, page: Page):
"""Test page load time."""
try:
start_time = await page.evaluate("performance.now()")
await page.reload()
await page.wait_for_load_state('networkidle')
end_time = await page.evaluate("performance.now()")
load_time = (end_time - start_time) / 1000 # Convert to seconds
if load_time > self.performance_thresholds['page_load_time']:
self._add_bug_report(
title="Slow Page Load Time",
severity=BugSeverity.MEDIUM,
description=f"Page load time is {load_time:.2f}s, exceeds threshold of {self.performance_thresholds['page_load_time']}s",
steps_to_reproduce=["Reload page", "Measure load time"],
expected_behavior="Page should load quickly",
actual_behavior=f"Page loads in {load_time:.2f}s",
url=page.url,
element_info={"load_time": load_time, "threshold": self.performance_thresholds['page_load_time']},
recommendations=["Optimize images", "Minify CSS/JS", "Use CDN", "Enable compression"]
)
except Exception as e:
logger.error(f"Page load time test error: {e}")
async def _check_for_errors(self, page: Page) -> bool:
"""Check for JavaScript errors on the page."""
try:
# Check console for errors
errors = await page.evaluate("""
() => {
if (window.fagunErrorMonitor) {
return window.fagunErrorMonitor.getErrors();
}
return [];
}
""")
return len(errors) > 0
except Exception:
return False
def _add_bug_report(self, title: str, severity: BugSeverity, description: str,
steps_to_reproduce: List[str], expected_behavior: str,
actual_behavior: str, url: str, element_info: Dict[str, Any],
recommendations: List[str]):
"""Add a bug report."""
bug = BugReport(
title=title,
severity=severity,
description=description,
steps_to_reproduce=steps_to_reproduce,
expected_behavior=expected_behavior,
actual_behavior=actual_behavior,
url=url,
element_info=element_info,
recommendations=recommendations
)
self.bugs_found.append(bug)
logger.info(f"🐛 Bug found: {title} ({severity.value})")
# Placeholder methods for other tests
async def _back_forward_test(self, page: Page):
"""Test browser back/forward functionality."""
pass
async def _refresh_test(self, page: Page):
"""Test page refresh functionality."""
pass
async def _url_manipulation_test(self, page: Page):
"""Test URL manipulation."""
pass
async def _test_invalid_form_data(self, form: Locator, page: Page):
"""Test form with invalid data."""
pass
async def _test_large_form_data(self, form: Locator, page: Page):
"""Test form with large data."""
pass
async def _test_special_characters(self, form: Locator, page: Page):
"""Test form with special characters."""
pass
async def _test_accessibility(self, page: Page):
"""Test accessibility features."""
pass
async def _test_hover_effects(self, page: Page):
"""Test hover effects."""
pass
async def _test_clickable_areas(self, page: Page):
"""Test clickable areas."""
pass
async def _test_scrolling_behavior(self, page: Page):
"""Test scrolling behavior."""
pass
async def _test_resource_loading(self, page: Page):
"""Test resource loading performance."""
pass
async def _test_memory_usage(self, page: Page):
"""Test memory usage."""
pass
async def _test_network_performance(self, page: Page):
"""Test network performance."""
pass
async def _test_csrf_vulnerabilities(self, page: Page):
"""Test CSRF vulnerabilities."""
pass
async def _test_clickjacking(self, page: Page):
"""Test clickjacking vulnerabilities."""
pass
async def _test_session_management(self, page: Page):
"""Test session management."""
pass
async def _test_authentication(self, page: Page):
"""Test authentication."""
pass
# Global enhanced testing engine
enhanced_ai_testing_engine = EnhancedAITestingEngine()