The Modern Page Object Model Framework for Mobile Test Automation
Write mobile tests that are maintainable, readable, and reliable
Quick Start β’ Documentation β’ Examples β’ Contributing
Tired of flaky mobile tests that break every release? Appom transforms mobile test automation with:
# Traditional approach π’
driver.find_element(:id, 'login_btn').click
sleep(2) # Hope the page loads...
driver.find_element(:xpath, '//input[@type="email"]').send_keys('user@test.com')
# Appom way π
login_page.login('user@test.com', 'password')
expect(home_page).to have_dashboard| π― Smart Page Objects | Semantic DSL that reads like natural language |
| π Intelligent Retry | Auto-retry with exponential backoff for flaky elements |
| π Performance Monitoring | Track test performance and identify bottlenecks |
| π¨ Visual Testing | Automated visual regression testing built-in |
| π‘οΈ Robust Error Handling | Detailed diagnostics with screenshots and context |
| π± Cross-Platform | Single codebase for iOS and Android |
gem install appomOr add to your Gemfile:
gem 'appom'require 'appom'
Appom.register_driver do
Appium::Driver.new({
caps: {
platformName: 'iOS',
deviceName: 'iPhone 15',
app: '/path/to/your/app.ipa'
},
appium_lib: { server_url: 'http://localhost:4723/wd/hub' }
})
endclass LoginPage < Appom::Page
element :email, :accessibility_id, 'email_field'
element :password, :accessibility_id, 'password_field'
element :login_btn, :accessibility_id, 'login_button'
def login(email, password)
self.email.set(email)
self.password.set(password)
login_btn.tap
end
endRSpec.describe 'Login Flow' do
it 'logs user in successfully' do
login_page = LoginPage.new
login_page.login('test@example.com', 'password')
expect(HomePage.new).to have_welcome_message
end
endThat's it! No more sleep(), no more flaky selectors, no more mysterious failures.
Advanced Page Object with Sections
class ShoppingPage < Appom::Page
section :header, HeaderSection, :id, 'header'
sections :products, ProductSection, :class, 'product-card'
def add_product_to_cart(product_name)
product = products.find { |p| p.name.text == product_name }
product.add_to_cart
wait_for_cart_update
end
end
class ProductSection < Appom::Section
element :name, :class, 'product-name'
element :price, :class, 'product-price'
element :add_btn, :class, 'add-to-cart-btn'
def add_to_cart
scroll_to_and_tap(:add_btn)
end
endSmart Waiting & Retry Logic
class PaymentPage < Appom::Page
element :card_field, :id, 'card_number'
element :submit_btn, :id, 'submit_payment'
def process_payment(card_number)
# Auto-retry for flaky elements
interact_with_retry(:card_field, :send_keys, text: card_number)
# Wait for specific conditions
tap_and_wait(:submit_btn)
wait_for_any(:success_message, :error_message, timeout: 30)
end
endVisual Testing Integration
class ProductPage < Appom::Page
def verify_product_display
# Automatic visual regression testing
take_visual_snapshot('product_page')
compare_visual_baseline('product_page', threshold: 0.95)
end
end- Complete Documentation - Comprehensive guide with advanced features
- API Reference - Detailed API documentation
- Best Practices - Testing patterns and conventions
- Troubleshooting - Common issues and solutions
Made with β€οΈ by the mobile testing community