📱 Appom
The Modern Page Object Model Framework for Mobile Test Automation
Write mobile tests that are maintainable, readable, and reliable
Quick Start • Documentation • Examples • Contributing
✨ Why Appom?
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🚀 Key Features
| 🎯 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 |
📦 Installation
gem install appomOr add to your Gemfile:
gem 'appom'⚡ Quick Start
1. Initialize 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' }
})
end2. Create Page Objects
class 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
end3. Write Tests
RSpec.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.
🎯 Examples
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
endclass 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
endclass 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📚 Documentation
- 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
⬆ Back to top