Intelligent Android App Testing Tool with Grafana Dashboards
Features • Installation • Quick Start • Grafana Setup • Documentation
SmartMonkey is an intelligent Android app testing tool that goes beyond traditional random monkey testing. While MonkeyRunner clicks randomly, SmartMonkey uses a weighted exploration strategy to intelligently test your Android applications with beautiful Grafana dashboards for visualization.
- 📊 Weighted Strategy: Prioritizes unvisited UI elements (10x weight) to maximize code coverage
- 🎯 Smart Targeting: Bonus scoring for buttons (1.5x) and submit actions (2x)
- 🔍 State Detection: MD5 hashing to avoid duplicate states
- 💥 Crash Detection: Automatically detects when app exits or moves to background
- 📸 Visual Documentation: Screenshots at every step with Grafana gallery
- Weighted Strategy: Unvisited elements get 10x priority
- Context-Aware: Recognizes buttons, text fields, and interactive elements
- State Hashing: Avoids testing duplicate UI states
- Real-time Monitoring: Detects when app stops running or moves to background
- Empty State Detection: Identifies UI deadlocks
- Detailed Reports: Full crash context with screenshots
- Beautiful Visualizations: Interactive test result dashboards
- Screenshot Gallery: Scrollable gallery of all test screenshots
- Test History: Track multiple test runs over time
- Drill-Down Navigation: Click test ID to view detailed results
- Full CLI Parameters: Device, package, steps, strategy all configurable
- Multi-device Support: Works with physical devices and emulators
- JSON & Text Reports: Both machine and human-readable formats
View all test runs with status, duration, and crash detection
Interactive screenshot gallery and detailed test metrics
- Python 3.9 or higher
- Android SDK with ADB installed
- At least one Android device or emulator connected
# Clone the repository
git clone https://github.com/yourusername/smartmonkey.git
cd smartmonkey
# Install dependencies
pip install -r requirements.txt
# Set PYTHONPATH
export PYTHONPATH=$(pwd):$PYTHONPATH
# Verify installation
python3 -m smartmonkey.cli.main --versionpython3 -m smartmonkey.cli.main list-devicesOutput:
Available devices:
- emulator-5556 (sdk_gphone64_arm64)
- RFCX919P8ZF (Samsung SM-A356N)
python3 -m smartmonkey.cli.main run \
--device emulator-5556 \
--package com.android.settings \
--steps 20# Run 5 tests with 20 steps each
for i in {1..5}; do
python3 -m smartmonkey.cli.main run \
--device emulator-5556 \
--package io.whatap.session.sample \
--steps 20 \
--strategy weighted \
--output ./reports/test_run_$(printf "%03d" $i)
sleep 2
donepython3 -m smartmonkey.cli.main run [OPTIONS]| Parameter | Short | Description | Default | Required |
|---|---|---|---|---|
--device |
-d |
Device serial number | Auto-detect | No* |
--package |
-p |
App package name | - | Yes |
--steps |
-n |
Maximum number of steps | 50 | No |
--strategy |
-s |
Exploration strategy (random or weighted) |
weighted |
No |
--output |
-o |
Output directory path | ./reports/<timestamp> |
No |
--screenshots |
- | Save screenshots | yes |
No |
--no-screenshots |
- | Disable screenshots | - | No |
* Required if multiple devices are connected
python3 -m smartmonkey.cli.main run --package com.example.apppython3 -m smartmonkey.cli.main run \
--device emulator-5556 \
--package com.example.app \
--steps 100 \
--strategy weighted \
--output ./my_test_resultspython3 -m smartmonkey.cli.main run \
--package com.example.app \
--no-screenshotspython3 -m smartmonkey.cli.main run \
--package com.example.app \
--strategy random \
--steps 50# macOS
brew install grafana
brew services start grafana
# Linux (Ubuntu/Debian)
sudo apt-get install -y adduser libfontconfig1
wget https://dl.grafana.com/oss/release/grafana_10.0.0_amd64.deb
sudo dpkg -i grafana_10.0.0_amd64.deb
sudo systemctl start grafana-server
# Access Grafana
open http://localhost:3000 # Default: admin/admin- Go to Configuration → Plugins
- Install Infinity Data Source plugin
- Install HTML Graphics Panel plugin (gapit-htmlgraphics-panel)
- Go to Connections → Data sources → Add data source
- Search and select Infinity
- Name it (e.g., "SmartMonkey Reports")
- Click Save & Test
cd /path/to/smartmonkey/reports
python3 -m http.server 8000Keep this running in a separate terminal.
- Go to Dashboards → Import
- Click Upload JSON file
- Select
grafana/dashboard-main.json - Select your Infinity data source
- Click Import
- Go to Dashboards → Import
- Click Upload JSON file
- Select
grafana/dashboard-detail.json - Select your Infinity data source
- Click Import
- Open SmartMonkey - Test Runs dashboard
- You'll see a list of all test runs
- Click on any Test ID to drill down to detailed results
- Browse the screenshot gallery and test metrics
smartmonkey/
├── smartmonkey/ # Main package
│ ├── cli/ # CLI interface
│ │ └── main.py # Command-line entry point
│ ├── device/ # Device communication (ADB)
│ │ ├── adb_manager.py # ADB wrapper
│ │ ├── app_manager.py # App lifecycle management
│ │ ├── device.py # Device abstraction
│ │ └── event_manager.py # Touch/swipe events
│ ├── exploration/ # UI exploration & strategies
│ │ ├── element.py # UI element representation
│ │ ├── exploration_engine.py # Main exploration logic
│ │ ├── state.py # UI state management
│ │ ├── ui_parser.py # UIAutomator parser
│ │ └── strategies/ # Exploration strategies
│ │ ├── base_strategy.py
│ │ ├── random_strategy.py
│ │ └── weighted_strategy.py
│ ├── reporting/ # Report generation
│ │ └── report_generator.py # JSON/Text reports
│ └── utils/ # Utilities
│ ├── logger.py # Logging setup
│ ├── helpers.py # Helper functions
│ └── exceptions.py # Custom exceptions
├── grafana/ # Grafana dashboard configs
│ ├── dashboard-main.json # Test list dashboard
│ └── dashboard-detail.json # Test detail dashboard
├── docs/ # Documentation
│ ├── design/ # Design documents
│ └── images/ # Screenshots
├── reports/ # Generated test reports (gitignored)
├── requirements.txt # Python dependencies
├── pyproject.toml # Project metadata
├── .gitignore # Git ignore rules
└── README.md # This file
After running a test, the following structure is created:
reports/
├── index.json # Test runs index (for Grafana)
└── test_run_001/
├── report.json # Structured test data
├── report.txt # Human-readable summary
└── screenshots/
├── screenshot_0000.png # Step 0 screenshot
├── screenshot_0001.png # Step 1 screenshot
└── ...
{
"start_time": "2025-10-24T10:33:31.743373",
"end_time": "2025-10-24T10:35:00.084500",
"duration_seconds": 88.341127,
"total_events": 20,
"unique_states": 13,
"total_states": 20,
"crash_detected": false,
"crash_info": null,
"states": [
{
"step": 0,
"timestamp": 1761201226.080551,
"datetime": "2025-10-24T10:33:31.743373",
"activity": "io.whatap.session.sample.Screen1Activity",
"element_count": 17,
"state_hash": "f0d3dd1f...",
"screenshot": "./screenshots/screenshot_0000.png",
"screenshot_url": "http://localhost:8000/test_run_001/screenshots/screenshot_0000.png"
}
],
"actions": [
{
"step": 0,
"timestamp": 1761201227.0,
"type": "tap",
"repr": "TapAction(element=Button, text='GO TO SCREEN 2')"
}
]
}============================================================
SmartMonkey Exploration Report
============================================================
Start Time: 2025-10-24 10:33:31
End Time: 2025-10-24 10:35:00
Duration: 88.3 seconds
Total Events: 20
Unique States: 13
Total States Visited: 20
States Explored:
------------------------------------------------------------
1. Screen1Activity (2 elements)
2. Screen2Activity (3 elements)
3. Screen3Activity (2 elements)
...
Actions Performed:
------------------------------------------------------------
tap: 15
back: 3
swipe_up: 2
- Prioritizes unvisited elements: 10x weight for new elements
- Better coverage: Explores unique UI states more thoroughly
- Smart targeting: Bonus for buttons and submit actions
- Recommended for: Thorough testing and code coverage
- Random selection: Picks any clickable element randomly
- Faster execution: No state tracking overhead
- Good for: Quick smoke testing and chaos engineering
- Use case: Finding unexpected crashes
# Check ADB connection
adb devices
# If no devices shown, restart ADB
adb kill-server
adb start-server
# Check device is authorized
adb devices
# Should show "device" not "unauthorized"# Check app is installed
adb shell pm list packages | grep <package>
# Launch app manually first
adb shell am start -n <package>/.MainActivity
# Check logcat for errors
adb logcat | grep <package>-
Check HTTP server is running:
curl http://localhost:8000/index.json
-
Verify Data Source URL:
- Should be
http://localhost:8000/ - Check Grafana Data Source settings
- Should be
-
Check browser console: F12 → Console tab for errors
-
Verify image URLs are accessible:
curl -I http://localhost:8000/test_run_001/screenshots/screenshot_0000.png
-
Check CORS settings: HTTP server should allow cross-origin requests
-
Refresh Grafana dashboard: Click refresh button or Ctrl+R
# Test Configuration
Device: Emulator (emulator-5556)
Package: io.whatap.session.sample
Steps: 20
Strategy: weighted
Duration: 88.3 seconds
# Results
✅ Total Events: 20
✅ Unique States: 13
✅ Screenshots: 20
✅ Status: Passed
# Actions Breakdown
tap: 15 (75%)
back: 3 (15%)
swipe_up: 2 (10%)Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Crash/ANR detection layer enhancements
- HTML report generation
- DFS and BFS exploration strategies
- Performance monitoring (FPS, memory, CPU)
- Configuration file support (YAML)
- Code coverage tracking
- ML-based exploration strategy
- CI/CD integration (GitHub Actions, Jenkins)
- Cloud testing support
- Android Debug Bridge (ADB) - Device communication
- UIAutomator - UI hierarchy parsing
- Grafana - Data visualization platform
- Infinity Data Source - JSON data loading for Grafana
- HTML Graphics Panel - Screenshot gallery rendering
- GitHub: yourusername/smartmonkey
- Issues: Report bugs or request features
Made with ❤️ by SmartMonkey Team
⭐ Star this repo if you find it useful!