Library Usage Guide¶
This guide demonstrates how to use the Optics Framework as a Python library for programmatic test automation.
Installation¶
Install the Optics Framework:
Quick Start¶
Basic Example¶
from optics_framework import Optics
# Initialize Optics
optics = Optics()
# Configure with driver and element sources
optics.setup(
driver_sources=[{"appium": {"enabled": True, "url": "http://localhost:4723"}}],
elements_sources=[{"appium_find_element": {"enabled": True}}]
)
# Launch app
optics.launch_app("com.example.app")
# Interact with elements
optics.press_element("submit_button")
optics.enter_text("username_field", "testuser")
# Verify elements
optics.validate_element("welcome_message")
# Cleanup
optics.quit()
Configuration¶
Configuration from Dictionary¶
from optics_framework import Optics
config = {
"driver_sources": [
{
"appium": {
"enabled": True,
"url": "http://localhost:4723",
"capabilities": {
"platformName": "Android",
"deviceName": "emulator-5554"
}
}
}
],
"elements_sources": [
{"appium_find_element": {"enabled": True}}
],
"text_detection": [
{"easyocr": {"enabled": True}}
],
"image_detection": [
{"templatematch": {"enabled": True}}
],
"project_path": "/path/to/project"
}
optics = Optics(config=config)
Configuration from YAML File¶
config.yaml:
driver_sources:
- appium:
enabled: true
url: "http://localhost:4723"
capabilities:
platformName: "Android"
deviceName: "emulator-5554"
elements_sources:
- appium_find_element:
enabled: true
text_detection:
- easyocr:
enabled: true
image_detection:
- templatematch:
enabled: true
project_path: "/path/to/project"
Configuration from YAML String¶
from optics_framework import Optics
yaml_config = """
driver_sources:
- appium:
enabled: true
url: "http://localhost:4723"
elements_sources:
- appium_find_element:
enabled: true
"""
optics = Optics()
optics.setup(config=yaml_config)
App Management¶
Launching Apps¶
# Launch app by package name
optics.launch_app("com.example.app")
# Launch other app
optics.launch_other_app("com.other.app")
# Get app version
version = optics.get_app_version()
print(f"App version: {version}")
# Get driver session ID
session_id = optics.get_driver_session_id()
print(f"Session ID: {session_id}")
App Lifecycle¶
# Launch app
optics.launch_app("com.example.app")
# Perform test operations
optics.press_element("button")
# Close and terminate app
optics.close_and_terminate_app()
# Or force terminate
optics.force_terminate_app()
Element Interactions¶
Pressing Elements¶
# Press element by ID
optics.press_element("submit_button")
# Press with fallback (tries multiple identifiers)
optics.press_element(["button1", "button2", "//button[@id='submit']"])
# Press by coordinates
optics.press_by_coordinates(100, 200)
# Press by percentage (50% x, 50% y)
optics.press_by_percentage(50, 50)
# Press element with index (if multiple matches)
optics.press_element_with_index("button", index=0)
Text Input¶
# Enter text in element
optics.enter_text("username_field", "testuser")
# Enter text directly (without element)
optics.enter_text_direct("input_field", "text")
# Enter text using keyboard
optics.enter_text_using_keyboard("field", "text")
# Enter number
optics.enter_number("number_field", 123)
# Clear element text
optics.clear_element_text("input_field")
Gestures¶
# Swipe from (x1, y1) to (x2, y2)
optics.swipe(100, 200, 300, 400)
# Swipe until element appears
optics.swipe_until_element_appears("target_element", direction="up")
# Swipe from element
optics.swipe_from_element("source_element", 300, 400)
# Scroll
optics.scroll(100, 200, 300, 400)
# Scroll until element appears
optics.scroll_until_element_appears("target_element", direction="down")
# Scroll from element
optics.scroll_from_element("source_element", 300, 400)
Other Actions¶
# Press keycode
optics.press_keycode(4) # Back button
# Get text from element
text = optics.get_text("element_id")
print(f"Element text: {text}")
# Sleep
optics.sleep(2) # Sleep for 2 seconds
# Execute script
result = optics.execute_script("mobile: shell", {"command": "echo hello"})
Verification¶
Element Validation¶
# Validate single element exists
optics.validate_element("welcome_message")
# Assert presence with rules
optics.assert_presence(["element1", "element2"], rule="all") # All must be present
optics.assert_presence(["element1", "element2"], rule="any") # Any must be present
# Validate screen (multiple elements)
optics.validate_screen(["header", "content", "footer"])
Screenshots and Page Source¶
# Capture screenshot
screenshot = optics.capture_screenshot()
print(f"Screenshot: {screenshot}")
# Capture page source
page_source = optics.capture_page_source()
print(f"Page source: {page_source}")
# Get interactive elements
elements = optics.get_interactive_elements()
for element in elements:
print(f"Element: {element}")
Flow Control¶
Conditional Execution¶
# Condition with variable
optics.condition("${status} == 'ready'", "proceed_keyword")
# Condition with expression
optics.condition("${count} > 10", "handle_large_count")
Data Operations¶
# Read data from CSV (element, source, optional query)
data = optics.read_data("${data}", "data.csv")
print(f"Data: {data}")
# Read with query: filter and column selection
data = optics.read_data("${users}", "users.csv", "status=='active';select=username,email")
# Read from a 2D list: first row = headers, following rows = data
data = optics.read_data("${items}", [["id", "name"], ["1", "a"], ["2", "b"]])
print(f"Data: {data}")
# Invoke API
response = optics.invoke_api("GET", "https://api.example.com/data")
print(f"API response: {response}")
Loops¶
# Run loop 5 times
optics.run_loop(5, "keyword_name")
# Run loop with condition
optics.run_loop(10, "process_item", condition="${status} == 'active'")
Evaluation¶
# Evaluate expression
result = optics.evaluate("${var1} + ${var2}")
print(f"Result: {result}")
# Date evaluation
future_date = optics.date_evaluate("today + 1 day")
past_date = optics.date_evaluate("today - 7 days")
Element Management¶
Adding Elements¶
# Add element
optics.add_element("submit_button", "//button[@id='submit']")
# Get element value
element_value = optics.get_element_value("submit_button")
print(f"Element value: {element_value}")
# Use element in keywords
optics.press_element("submit_button") # Uses stored element
# Use element variable
optics.press_element("${submit_button}") # Resolves variable
Element Variables¶
# Add multiple elements
optics.add_element("username", "//input[@name='user']")
optics.add_element("password", "//input[@name='pass']")
optics.add_element("submit", "//button[@type='submit']")
# Use in sequence
optics.enter_text("${username}", "testuser")
optics.enter_text("${password}", "testpass")
optics.press_element("${submit}")
Session Management¶
Basic Session Lifecycle¶
from optics_framework import Optics
# Create and configure session
optics = Optics()
optics.setup(config=config)
# Use session
optics.launch_app("com.example.app")
optics.press_element("button")
# Cleanup session
optics.quit()
Context Manager Pattern¶
from contextlib import contextmanager
from optics_framework import Optics
@contextmanager
def optics_session(config):
"""Context manager for automatic session cleanup."""
optics = Optics()
optics.setup(config=config)
try:
yield optics
finally:
optics.quit()
# Usage
config = {...}
with optics_session(config) as optics:
optics.launch_app("com.example.app")
optics.press_element("button")
# Session automatically cleaned up on exit
Multiple Sessions¶
from optics_framework import Optics
# Create multiple instances for different sessions
optics1 = Optics(config=config1)
optics2 = Optics(config=config2)
# Each instance has its own session
optics1.launch_app("app1")
optics2.launch_app("app2")
# Cleanup both
optics1.quit()
optics2.quit()
Error Handling¶
Basic Error Handling¶
from optics_framework import Optics
from optics_framework.common.error import OpticsError
optics = Optics()
optics.setup(config=config)
try:
optics.press_element("nonexistent_element")
except OpticsError as e:
print(f"Error code: {e.code}")
print(f"Error message: {e.message}")
print(f"Error details: {e.details}")
Handling Specific Errors¶
from optics_framework.common.error import OpticsError, Code
try:
optics.press_element("button")
except OpticsError as e:
if e.code == Code.E0101:
print("Driver not initialized")
elif e.code == Code.E0201:
print("Element not found")
else:
print(f"Other error: {e.message}")
Complete Example¶
from optics_framework import Optics
from optics_framework.common.error import OpticsError
def test_login_flow():
"""Complete test example."""
config = {
"driver_sources": [
{"appium": {"enabled": True, "url": "http://localhost:4723"}}
],
"elements_sources": [
{"appium_find_element": {"enabled": True}}
],
"project_path": "/path/to/project"
}
optics = Optics()
try:
# Setup
optics.setup(config=config)
# Launch app
optics.launch_app("com.example.app")
# Add elements
optics.add_element("username", "//input[@id='username']")
optics.add_element("password", "//input[@id='password']")
optics.add_element("login_button", "//button[@id='login']")
# Perform login
optics.enter_text("${username}", "testuser")
optics.enter_text("${password}", "testpass")
optics.press_element("${login_button}")
# Verify login
optics.validate_element("welcome_message")
# Capture screenshot
screenshot = optics.capture_screenshot()
print(f"Screenshot saved: {screenshot}")
except OpticsError as e:
print(f"Test failed: {e.message}")
raise
finally:
# Cleanup
optics.quit()
if __name__ == "__main__":
test_login_flow()
Best Practices¶
1. Configuration Management¶
- Store configuration in YAML files for complex setups
- Use environment variables for sensitive data
- Keep configuration separate from test logic
2. Resource Cleanup¶
- Always call
quit()when done - Use context managers for automatic cleanup
- Handle exceptions to ensure cleanup
3. Element Management¶
- Store frequently used elements
- Use descriptive element names
- Leverage fallback parameters for resilience
4. Error Handling¶
- Wrap operations in try/except blocks
- Handle
OpticsErrorspecifically - Log errors for debugging
5. Code Organization¶
- Separate configuration from test logic
- Create helper functions for common operations
- Organize tests into logical modules
Related Documentation¶
- Library Layer Architecture - Detailed architecture documentation
- Keyword Usage - Complete keyword reference
- Configuration - Configuration guide
- REST API Usage - REST API endpoint reference
- API Reference - Python API documentation