skills/mobile-testing/SKILL.md
# Mobile Testing Skill Reference for manual QA testing of KMP Compose Multiplatform apps using MCP mobile automation tools. ## Quick Reference: MCP Tools | Tool | Purpose | When to Use | |------|---------|-------------| | `list_devices` | Find emulators/devices | Start of test | | `set_device` | Select target device | Multi-device testing | | `launch_app` | Start application | Begin test session | | `screenshot` | Capture screen state | Visual verification | | `get_ui` | Get UI hierarchy | El
npx skillsauth add andvl1/claude-plugin skills/mobile-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference for manual QA testing of KMP Compose Multiplatform apps using MCP mobile automation tools.
| Tool | Purpose | When to Use |
|------|---------|-------------|
| list_devices | Find emulators/devices | Start of test |
| set_device | Select target device | Multi-device testing |
| launch_app | Start application | Begin test session |
| screenshot | Capture screen state | Visual verification |
| get_ui | Get UI hierarchy | Element discovery |
| tap | Click on element | Button clicks, navigation |
| swipe | Scroll/gesture | Lists, carousels |
| input_text | Type text | Form fields |
| press_key | Hardware keys | BACK, HOME, ENTER |
| get_logs | Read device logs | Error detection |
| shell | Execute commands | Advanced debugging |
Device: emulator-5554
Package: com.your-project.admin
Use: Daily development testing
Setup: Android Studio -> AVD Manager
Device: iPhone 15 Simulator
Bundle ID: com.your-project.admin
Use: iOS-specific testing
Setup: Xcode -> Simulators
Android: USB debugging enabled
iOS: Developer mode enabled
Use: Final validation, performance testing
Run: ./gradlew :composeApp:run
Platforms: macOS, Windows, Linux
Use: Desktop-specific features
list_devices(platform: "android") # Find devices
set_device(deviceId: "emulator-5554") # Select device
clear_logs() # Clear log buffer
launch_app(package: "com.your-project.admin")
wait(ms: 2000) # Wait for launch
screenshot() # Verify initial state
get_ui() # Discover elements
tap(text: "Settings") # Navigate
wait(ms: 500)
screenshot() # Verify transition
tap(text: "Search") # Focus field
input_text(text: "test query") # Type text
press_key(key: "ENTER") # Submit
wait(ms: 1000)
screenshot()
get_logs(package: "com.your-project.admin", level: "E")
# Check for: crashes, exceptions, errors
get_current_activity() # Verify screen
get_system_info() # Check resources
list_devices() # All devices
list_devices(platform: "android") # Android only
list_devices(platform: "ios") # iOS only
set_device(deviceId: "emulator-5554")
set_device(deviceId: "iPhone 15")
get_system_info()
# Returns: battery level, memory usage (Android)
launch_app(package: "com.your-project.admin") # Android
launch_app(package: "com.your-project.admin") # iOS (bundle ID)
stop_app(package: "com.your-project.admin") # Force stop
install_app(path: "/path/to/app.apk") # Android
install_app(path: "/path/to/App.app") # iOS Simulator
get_current_activity() # Android only
# Returns: current package/activity
screenshot() # Default quality
screenshot(quality: 90) # Higher quality
screenshot(maxWidth: 400, maxHeight: 800) # Smaller size
get_ui() # Interactive elements
get_ui(showAll: true) # All elements
# Returns: UI hierarchy with element refs
tap(x: 200, y: 400) # By coordinates
tap(text: "Settings") # By text (Android)
tap(index: 5) # By index (Android)
tap(resourceId: "btn_save") # By ID (Android)
long_press(x: 200, y: 400) # Default 1000ms
long_press(x: 200, y: 400, duration: 2000) # Custom duration
long_press(text: "Item") # By text (Android)
swipe(direction: "up") # Scroll down
swipe(direction: "down") # Scroll up
swipe(direction: "left") # Next page
swipe(direction: "right") # Previous page
swipe(x1: 200, y1: 800, x2: 200, y2: 200) # Custom swipe
swipe(x1: 200, y1: 400, x2: 200, y2: 400, duration: 500) # Slow swipe
input_text(text: "Hello World") # Type into focused field
press_key(key: "BACK") # Hardware back
press_key(key: "HOME") # Home button
press_key(key: "ENTER") # Enter/Return
press_key(key: "TAB") # Tab key
press_key(key: "DELETE") # Delete/Backspace
press_key(key: "VOLUME_UP") # Volume up
press_key(key: "VOLUME_DOWN") # Volume down
find_element(text: "Settings") # Android only
find_element(resourceId: "btn_save") # Android only
find_element(className: "Button") # Android only
find_element(clickable: true) # Filter by state
get_logs() # Last 100 lines
get_logs(lines: 200) # More lines
get_logs(package: "com.your-project.admin") # Filter by app
get_logs(level: "E") # Errors only
get_logs(tag: "NetworkClient") # Android: by tag
# Log levels (Android): V, D, I, W, E, F
# Log levels (iOS): debug, info, default, error, fault
clear_logs() # Android only
# Android (ADB shell)
shell(command: "dumpsys activity activities") # Current activities
shell(command: "pm list packages") # Installed packages
shell(command: "svc wifi disable") # Disable WiFi
shell(command: "svc wifi enable") # Enable WiFi
shell(command: "input keyevent 26") # Power button
# iOS (simctl)
shell(command: "status_bar override --time '9:41'")
shell(command: "privacy grant all com.your-project.admin")
wait(ms: 1000) # Wait 1 second
wait(ms: 500) # Wait 500ms
open_url(url: "https://your-project.ru") # Open in browser
FATAL EXCEPTION -> App crash
ANR in com.your-project.admin -> App not responding
java.lang.NullPointerException -> Null reference crash
java.lang.OutOfMemoryError -> Memory issue
Process: com.your-project.admin, PID... -> Crash with stack trace
NetworkError -> API call failed
SocketTimeoutException -> Network timeout
UnknownHostException -> No network/DNS issue
SSLHandshakeException -> Certificate issue
JsonParseException -> Malformed response
IllegalStateException: Expected -> State mismatch
Composition failed -> UI rendering error
Recomposition loop -> Infinite recomposition
Navigation error -> Decompose issue
clear_logs()launch_app(package: "com.your-project.admin")wait(ms: 3000)screenshot() -> Verify home screenget_logs(level: "E") -> No crashesget_ui() -> Find navigation elementstap(text: "Settings") -> Navigatewait(ms: 500)get_current_activity() -> Verify screenscreenshot()press_key(key: "BACK") -> Navigate backwait(ms: 300)screenshot() -> Verify returntap(text: "Name") -> Focus fieldinput_text(text: "Test User")tap(text: "Email")input_text(text: "[email protected]")tap(text: "Save")wait(ms: 1000)screenshot() -> Verify successget_logs(level: "E") -> No errorsscreenshot() -> Initial stateswipe(direction: "up") -> Scroll downwait(ms: 300)screenshot() -> New itemsswipe(direction: "up") x3 -> Load moreget_ui() -> Verify items loadedscreenshot() -> Record stateshell(command: "input keyevent 26") -> Power button (lock)wait(ms: 1000)shell(command: "input keyevent 26") -> Unlockscreenshot() -> Verify state preservedpress_key(key: "HOME") -> Background appwait(ms: 2000)launch_app(package: "com.your-project.admin") -> Resumescreenshot() -> Verify navigation stateshell(command: "svc wifi disable") -> Disable networkwait(ms: 2000)screenshot() -> Verify error UIget_logs(level: "E") -> Check error loggedshell(command: "svc wifi enable") -> Enable networkwait(ms: 1000)screenshot() -> Verify successstop_app(package: "com.your-project.admin")shell(command: "am start -a android.intent.action.VIEW -d 'your-project://chat/123'")wait(ms: 2000)screenshot() -> Verify deep link handledget_current_activity() -> Verify correct screenPackage name: com.your-project.admin
Log levels: V (Verbose), D (Debug), I (Info), W (Warning), E (Error), F (Fatal)
Shell: ADB commands available
Emulator: emulator-5554 (default)
Bundle ID: com.your-project.admin
Log levels: debug, info, default, error, fault
Shell: simctl commands available
Simulator: iPhone 15 (default)
Run: ./gradlew :composeApp:run
Platforms: macOS, Windows, Linux
Testing: Manual (no MCP tools)
Focus: Keyboard navigation, window resize
Run: ./gradlew :composeApp:wasmJsBrowserRun
Testing: Use Chrome testing tools
Focus: Browser compatibility
| Limitation | Workaround | |-----------|-----------| | iOS get_ui limited | Use screenshot + coordinates | | find_element Android only | Use tap(x, y) on iOS | | clear_logs Android only | Restart simulator on iOS | | shell varies by platform | Use platform-specific commands | | No network mocking | Use shell to disable WiFi | | No rotation via MCP | Use shell input commands |
# Device info
adb shell getprop ro.build.version.sdk # API level
adb shell dumpsys battery # Battery status
adb shell dumpsys meminfo com.your-project.admin # Memory usage
# Screen control
adb shell input keyevent 26 # Power button
adb shell input keyevent 82 # Menu button
adb shell settings put system screen_brightness 200 # Brightness
# Network
adb shell svc wifi disable # WiFi off
adb shell svc wifi enable # WiFi on
adb shell svc data disable # Mobile data off
# App control
adb shell pm clear com.your-project.admin # Clear app data
adb shell am force-stop com.your-project.admin # Force stop
adb shell am start -a android.intent.action.VIEW -d "your-project://path" # Deep link
# Input
adb shell input text "hello" # Type text
adb shell input tap 200 400 # Tap at coords
adb shell input swipe 200 800 200 200 # Swipe gesture
# Device control
xcrun simctl boot "iPhone 15" # Boot simulator
xcrun simctl shutdown "iPhone 15" # Shutdown
xcrun simctl erase "iPhone 15" # Reset simulator
# App control
xcrun simctl install booted /path/to/App.app # Install app
xcrun simctl uninstall booted com.your-project.admin # Uninstall
xcrun simctl launch booted com.your-project.admin # Launch app
xcrun simctl terminate booted com.your-project.admin # Terminate
# Permissions
xcrun simctl privacy booted grant all com.your-project.admin # Grant all
xcrun simctl privacy booted reset all com.your-project.admin # Reset
# Status bar
xcrun simctl status_bar booted override --time "9:41" # Set time
xcrun simctl status_bar booted clear # Reset
# Screenshots/Recording
xcrun simctl io booted screenshot /path/to/screenshot.png
xcrun simctl io booted recordVideo /path/to/video.mp4
development
Effective Go patterns — idiomatic code, testing, benchmarks, project layout. Always use Go 1.21+ patterns.
development
Go microservices — gRPC, REST, cloud-native patterns, service discovery, circuit breakers, observability, health checks, graceful shutdown.
development
Go concurrency mastery — goroutines, channels, context, sync primitives, patterns, performance.
testing
Android WorkManager for guaranteed background execution - use for deferred tasks, periodic syncs, file uploads, notifications, and task chains. Covers CoroutineWorker, constraints, chaining, testing, and troubleshooting. Use when implementing background work that needs reliable execution across app restarts and doze mode.