qa-expert
Included with Lifetime
$97 forever
Expert-level quality assurance, testing strategies, automation, and QA processes
qaqatestingtest-automationquality-assuranceselenium
What this skill does
# Quality Assurance Expert
Expert guidance for quality assurance, testing strategies, test automation, and QA best practices.
## Core Concepts
### Testing Types
- Unit testing
- Integration testing
- System testing
- Acceptance testing
- Regression testing
- Performance testing
- Security testing
### Test Automation
- Selenium WebDriver
- Cypress, Playwright
- API testing (Postman, REST Assured)
- Mobile testing (Appium)
- CI/CD integration
- Test frameworks (JUnit, pytest, Jest)
### QA Processes
- Test planning
- Test case design
- Defect management
- Test metrics and reporting
- Risk-based testing
- Exploratory testing
## Test Automation Framework
```python
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from typing import Dict, List
class BasePage:
"""Base page object"""
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def find_element(self, locator):
return self.wait.until(EC.presence_of_element_located(locator))
def click(self, locator):
element = self.find_element(locator)
element.click()
def type_text(self, locator, text):
element = self.find_element(locator)
element.clear()
element.send_keys(text)
def get_text(self, locator):
element = self.find_element(locator)
return element.text
class LoginPage(BasePage):
"""Login page object"""
USERNAME_INPUT = (By.ID, "username")
PASSWORD_INPUT = (By.ID, "password")
LOGIN_BUTTON = (By.ID, "login-button")
ERROR_MESSAGE = (By.CLASS_NAME, "error-message")
def login(self, username: str, password: str):
self.type_text(self.USERNAME_INPUT, username)
self.type_text(self.PASSWORD_INPUT, password)
self.click(self.LOGIN_BUTTON)
def get_error_message(self):
return self.get_text(self.ERROR_MESSAGE)
class TestRunner:
"""Test execution framework"""
def __init__(self, browser: str = "chrome"):
self.browser = browser
self.driver = None
self.results = []
def setup(self):
if self.browser == "chrome":
options = webdriver.ChromeOptions()
options.add_argument("--headless")
self.driver = webdriver.Chrome(options=options)
elif self.browser == "firefox":
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(10)
def teardown(self):
if self.driver:
self.driver.quit()
def run_test(self, test_func, test_name: str):
try:
test_func()
self.results.append({"test": test_name, "status": "PASS"})
except Exception as e:
self.results.append({
"test": test_name,
"status": "FAIL",
"error": str(e)
})
def generate_report(self) -> Dict:
total = len(self.results)
passed = sum(1 for r in self.results if r["status"] == "PASS")
failed = total - passed
return {
"total": total,
"passed": passed,
"failed": failed,
"pass_rate": (passed / total * 100) if total > 0 else 0,
"results": self.results
}
# Pytest fixtures
@pytest.fixture
def driver():
options = webdriver.ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome(options=options)
yield driver
driver.quit()
@pytest.fixture
def login_page(driver):
driver.get("https://example.com/login")
return LoginPage(driver)
# Test cases
def test_successful_login(login_page):
login_page.login("testuser", "password123")
assert "Dashboard" in login_page.driver.title
def test_invalid_credentials(login_page):
login_page.login("invalid", "wrong")
error = login_page.get_error_message()
assert "Invalid credentials" in error
```
## API Testing
```python
import requests
from typing import Dict, Any
class APITestClient:
"""API testing client"""
def __init__(self, base_url: str):
self.base_url = base_url
self.session = requests.Session()
self.test_results = []
def test_get_endpoint(self, endpoint: str, expected_status: int = 200,
expected_keys: List[str] = None) -> Dict:
"""Test GET endpoint"""
url = f"{self.base_url}{endpoint}"
response = self.session.get(url)
result = {
"endpoint": endpoint,
"method": "GET",
"status_code": response.status_code,
"passed": response.status_code == expected_status
}
if expected_keys and response.status_code == 200:
data = response.json()
missing_keys = [k for k in expected_keys if k not in data]
result["missing_keys"] = missing_keys
result["passed"] = result["passed"] and len(missing_keys) == 0
self.test_results.append(result)
return result
def test_post_endpoint(self, endpoint: str, payload: Dict,
expected_status: int = 201) -> Dict:
"""Test POST endpoint"""
url = f"{self.base_url}{endpoint}"
response = self.session.post(url, json=payload)
result = {
"endpoint": endpoint,
"method": "POST",
"status_code": response.status_code,
"passed": response.status_code == expected_status,
"response_time_ms": response.elapsed.total_seconds() * 1000
}
self.test_results.append(result)
return result
def test_authentication(self, login_endpoint: str,
credentials: Dict) -> bool:
"""Test API authentication"""
response = self.session.post(
f"{self.base_url}{login_endpoint}",
json=credentials
)
if response.status_code == 200:
token = response.json().get("token")
if token:
self.session.headers.update({"Authorization": f"Bearer {token}"})
return True
return False
def test_rate_limiting(self, endpoint: str, requests_count: int = 100):
"""Test rate limiting"""
url = f"{self.base_url}{endpoint}"
rate_limited = False
for i in range(requests_count):
response = self.session.get(url)
if response.status_code == 429:
rate_limited = True
break
return {
"rate_limited": rate_limited,
"requests_before_limit": i if rate_limited else requests_count
}
```
## Test Data Management
```python
import random
from faker import Faker
from typing import Dict, List
class TestDataGenerator:
"""Generate test data"""
def __init__(self):
self.faker = Faker()
def generate_user(self) -> Dict:
"""Generate user test data"""
return {
"username": self.faker.user_name(),
"email": self.faker.email(),
"first_name": self.faker.first_name(),
"last_name": self.faker.last_name(),
"phone": self.faker.phone_number(),
"address": {
"street": self.faker.street_address(),
"city": self.faker.city(),
"state": self.faker.state(),
"zip": self.faker.zipcode()
}
}
def generate_users(self, count: int) -> List[Dict]:
"""Generate multiple users"""
return [self.generate_user() for _ in range(count)]
def generate_order(self, user_id: str) -> Dict:
"""Generate order test data"""
return {
"order_id": self.faker.uuid4(),
"user_id": user_id,
"items": [
{
"product_id": self.faker.uuid4(),
"qu