significant android work
This commit is contained in:
239
android/firebase-test-lab/run_robo_tests.sh
Executable file
239
android/firebase-test-lab/run_robo_tests.sh
Executable file
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Run Robo Tests on Firebase Test Lab
|
||||
# =============================================================================
|
||||
# This script runs Robo exploratory tests on Firebase Test Lab across the
|
||||
# configured device matrix. Robo tests automatically crawl the app UI to
|
||||
# find crashes and ANRs without requiring instrumented test code.
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. gcloud CLI installed and authenticated (gcloud auth login)
|
||||
# 2. Firebase project created and Blaze plan enabled
|
||||
# 3. Google Play Console linked to Firebase project (optional, for deep links)
|
||||
# 4. Service account with Firebase Test Lab admin role
|
||||
#
|
||||
# Usage:
|
||||
# ./run_robo_tests.sh [options]
|
||||
#
|
||||
# Options:
|
||||
# --project-id Firebase project ID (default: kordant-android)
|
||||
# --app-aab Path to app AAB (default: auto-detected)
|
||||
# --app-apk Path to app APK (default: auto-detected)
|
||||
# --robo-script Path to robo script JSON (default: robo_script.json)
|
||||
# --timeout Max robo crawl time in seconds (default: 600)
|
||||
# --dry-run Print gcloud command without executing
|
||||
# --help Show this help message
|
||||
#
|
||||
# Reference: https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
# Default values
|
||||
PROJECT_ID="${FIREBASE_PROJECT_ID:-kordant-android}"
|
||||
APP_PATH=""
|
||||
ROBO_SCRIPT="${SCRIPT_DIR}/robo_script.json"
|
||||
MAX_CRAWL_TIME=600
|
||||
DRY_RUN=false
|
||||
|
||||
# Device matrix from test_matrix_config.yaml (generated via gcloud --device flags)
|
||||
# Each device runs with each orientation and locale combination
|
||||
declare -a DEVICE_ARGS=(
|
||||
# Pixel 6 - Primary target device (API 33)
|
||||
"--device model=Pixel6,version=33,locale=en_US,orientation=portrait"
|
||||
"--device model=Pixel6,version=33,locale=en_US,orientation=landscape"
|
||||
"--device model=Pixel6,version=33,locale=es_ES,orientation=portrait"
|
||||
"--device model=Pixel6,version=33,locale=es_ES,orientation=landscape"
|
||||
|
||||
# Pixel 4 - Older Pixel device (API 30)
|
||||
"--device model=Pixel4,version=30,locale=en_US,orientation=portrait"
|
||||
"--device model=Pixel4,version=30,locale=en_US,orientation=landscape"
|
||||
"--device model=Pixel4,version=30,locale=es_ES,orientation=portrait"
|
||||
"--device model=Pixel4,version=30,locale=es_ES,orientation=landscape"
|
||||
|
||||
# Samsung Galaxy S21 - Popular Samsung device (API 31)
|
||||
"--device model=GalaxyS21,version=31,locale=en_US,orientation=portrait"
|
||||
"--device model=GalaxyS21,version=31,locale=en_US,orientation=landscape"
|
||||
"--device model=GalaxyS21,version=31,locale=es_ES,orientation=portrait"
|
||||
"--device model=GalaxyS21,version=31,locale=es_ES,orientation=landscape"
|
||||
|
||||
# Xiaomi Redmi Note 8 - Budget device (API 29)
|
||||
"--device model=RedmiNote8,version=29,locale=en_US,orientation=portrait"
|
||||
"--device model=RedmiNote8,version=29,locale=en_US,orientation=landscape"
|
||||
"--device model=RedmiNote8,version=29,locale=es_ES,orientation=portrait"
|
||||
"--device model=RedmiNote8,version=29,locale=es_ES,orientation=landscape"
|
||||
|
||||
# Low-end device - Minimum spec target (API 28, 2GB RAM equivalent)
|
||||
"--device model=AquestM2,version=28,locale=en_US,orientation=portrait"
|
||||
"--device model=AquestM2,version=28,locale=en_US,orientation=landscape"
|
||||
"--device model=AquestM2,version=28,locale=es_ES,orientation=portrait"
|
||||
"--device model=AquestM2,version=28,locale=es_ES,orientation=landscape"
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# Helper: Print usage
|
||||
# ============================================================
|
||||
usage() {
|
||||
grep "^#" "$0" | grep -v "^#!/" | sed 's/^# //'
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Parse arguments
|
||||
# ============================================================
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--project-id)
|
||||
PROJECT_ID="$2"
|
||||
shift 2
|
||||
;;
|
||||
--app-aab)
|
||||
APP_PATH="$2"
|
||||
shift 2
|
||||
;;
|
||||
--app-apk)
|
||||
APP_PATH="$2"
|
||||
shift 2
|
||||
;;
|
||||
--robo-script)
|
||||
ROBO_SCRIPT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--timeout)
|
||||
MAX_CRAWL_TIME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Usage: $0 --help"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ============================================================
|
||||
# Auto-detect APK/AAB path if not provided
|
||||
# ============================================================
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
# Prefer AAB for more accurate Play Store representation
|
||||
APP_PATH=$(find "$PROJECT_DIR/android/app/build/outputs/bundle" -name "*-release.aab" 2>/dev/null | head -1)
|
||||
|
||||
# Fall back to APK if AAB not found
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
APP_PATH=$(find "$PROJECT_DIR/android/app/build/outputs/apk" -name "*-release.apk" 2>/dev/null | head -1)
|
||||
fi
|
||||
|
||||
# Last resort: any APK
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
APP_PATH=$(find "$PROJECT_DIR/android/app/build/outputs/apk" -name "*.apk" 2>/dev/null | head -1)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
echo "Error: Could not find app APK or AAB."
|
||||
echo ""
|
||||
echo "Build the app first:"
|
||||
echo " ./gradlew :app:assembleProdRelease"
|
||||
echo " # or for AAB:"
|
||||
echo " ./gradlew :app:bundleProdRelease"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$ROBO_SCRIPT" ]; then
|
||||
echo "Warning: Robo script not found at $ROBO_SCRIPT"
|
||||
echo "Robo will run without guided script (fully autonomous crawl)."
|
||||
ROBO_SCRIPT=""
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# Determine type flag based on file extension
|
||||
# ============================================================
|
||||
if [[ "$APP_PATH" == *.aab ]]; then
|
||||
TYPE_FLAG="--type robo"
|
||||
APP_FLAG="--app-package com.kordant.android"
|
||||
AAB_FLAG="--aab \"$APP_PATH\""
|
||||
APK_FLAG=""
|
||||
else
|
||||
TYPE_FLAG="--type robo"
|
||||
APP_FLAG=""
|
||||
AAB_FLAG=""
|
||||
APK_FLAG="--app \"$APP_PATH\""
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# Print configuration
|
||||
# ============================================================
|
||||
echo "=========================================="
|
||||
echo "Firebase Test Lab - Robo Tests"
|
||||
echo "=========================================="
|
||||
echo "Project ID: $PROJECT_ID"
|
||||
echo "App: $APP_PATH"
|
||||
echo "Robo Script: ${ROBO_SCRIPT:-none (fully autonomous)}"
|
||||
echo "Max Crawl Time: ${MAX_CRAWL_TIME}s"
|
||||
echo "Devices: ${#DEVICE_ARGS[@]} configurations"
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# Build gcloud command
|
||||
# ============================================================
|
||||
GCLOUD_CMD="gcloud firebase test android run \
|
||||
$TYPE_FLAG \
|
||||
--project \"$PROJECT_ID\" \
|
||||
$APP_FLAG \
|
||||
$AAB_FLAG \
|
||||
$APK_FLAG \
|
||||
--timeout 60m \
|
||||
--max-crawl-time $MAX_CRAWL_TIME \
|
||||
--record-video \
|
||||
--performance-metrics \
|
||||
--results-history-name \"Kordant Android Robo Tests\""
|
||||
|
||||
# Add robo script if available
|
||||
if [ -n "$ROBO_SCRIPT" ]; then
|
||||
GCLOUD_CMD="$GCLOUD_CMD --robo-script \"$ROBO_SCRIPT\""
|
||||
fi
|
||||
|
||||
# Add device configurations
|
||||
for device in "${DEVICE_ARGS[@]}"; do
|
||||
GCLOUD_CMD="$GCLOUD_CMD $device"
|
||||
done
|
||||
|
||||
echo "Command:"
|
||||
echo "$GCLOUD_CMD"
|
||||
echo ""
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo "DRY RUN - Command not executed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# Execute
|
||||
# ============================================================
|
||||
echo "Starting Robo tests..."
|
||||
echo ""
|
||||
eval "$GCLOUD_CMD"
|
||||
|
||||
EXIT_CODE=$?
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo ""
|
||||
echo "✅ Robo tests completed successfully!"
|
||||
echo "View results in Firebase Console: https://console.firebase.google.com/project/$PROJECT_ID/testlab"
|
||||
echo "Review crawl maps, screenshots, and videos for each device."
|
||||
else
|
||||
echo ""
|
||||
echo "❌ Robo tests failed with exit code $EXIT_CODE"
|
||||
echo "View results in Firebase Console: https://console.firebase.google.com/project/$PROJECT_ID/testlab"
|
||||
fi
|
||||
|
||||
exit $EXIT_CODE
|
||||
Reference in New Issue
Block a user