android flesh out

This commit is contained in:
2026-06-01 12:58:34 -04:00
parent ba73daa66c
commit 542172d1e8
183 changed files with 26946 additions and 761 deletions

View File

@@ -0,0 +1,139 @@
{
"name": "Kordant Robo Test Script",
"description": "Robo test script for Kordant Android app - guides login and primary screens",
"steps": [
{
"action_type": "wait",
"timeout_seconds": 10
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Get Started",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 5
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Sign In",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 3
},
{
"action_type": "click",
"element": {
"resource_name": "com.kordant.android:id/email_input",
"text": "",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "text_input",
"element": {
"resource_name": "com.kordant.android:id/email_input",
"text": "",
"content_description": ""
},
"text": "test-user-${ROBO_ID}@kordant.com",
"timeout_seconds": 5
},
{
"action_type": "click",
"element": {
"resource_name": "com.kordant.android:id/password_input",
"text": "",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "text_input",
"element": {
"resource_name": "com.kordant.android:id/password_input",
"text": "",
"content_description": ""
},
"text": "",
"timeout_seconds": 5
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Sign In",
"content_description": ""
},
"timeout_seconds": 10
},
{
"action_type": "wait",
"timeout_seconds": 15
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Dashboard",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 10
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Services",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 10
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Alerts",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 10
},
{
"action_type": "click",
"element": {
"resource_name": "",
"text": "Settings",
"content_description": ""
},
"timeout_seconds": 5
},
{
"action_type": "wait",
"timeout_seconds": 10
}
]
}

View File

@@ -0,0 +1,171 @@
#!/usr/bin/env bash
# =============================================================================
# Run Instrumentation Tests on Firebase Test Lab
# =============================================================================
# This script runs the Android instrumentation tests (UI tests) on Firebase
# Test Lab across the configured device matrix.
#
# 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
# 4. Service account with Firebase Test Lab admin role
#
# Usage:
# ./run_instrumentation_tests.sh [options]
#
# Options:
# --project-id Firebase project ID (default: kordant-android)
# --device-model Specific device model (runs all by default)
# --api-level Specific API level (runs all by default)
# --orientation Specific orientation: portrait|landscape (runs both by default)
# --locale Specific locale (runs all by default)
# --app-apk Path to app APK (default: auto-detected)
# --test-apk Path to test APK (default: auto-detected)
# --dry-run Print gcloud command without executing
# --help Show this help message
# =============================================================================
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_APK=""
TEST_APK=""
DRY_RUN=false
# Device matrix from test_matrix_config.yaml
DEVICES=(
"--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"
"--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"
"--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"
"--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"
"--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"
)
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--project-id)
PROJECT_ID="$2"
shift 2
;;
--app-apk)
APP_APK="$2"
shift 2
;;
--test-apk)
TEST_APK="$2"
shift 2
;;
--dry-run)
DRY_RUN=true
shift
;;
--help)
grep "^#" "$0" | grep -v "^#!/" | sed 's/^# //'
exit 0
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 --help"
exit 1
;;
esac
done
# Auto-detect APK paths if not provided
if [ -z "$APP_APK" ]; then
# Try to find release APK
APP_APK=$(find "$PROJECT_DIR/android/app/build/outputs/apk" -name "*-release.apk" 2>/dev/null | head -1)
if [ -z "$APP_APK" ]; then
APP_APK=$(find "$PROJECT_DIR/android/app/build/outputs/apk" -name "*.apk" 2>/dev/null | head -1)
fi
fi
if [ -z "$TEST_APK" ]; then
TEST_APK=$(find "$PROJECT_DIR/android/app/build/outputs/apk" -name "*androidTest*.apk" 2>/dev/null | head -1)
if [ -z "$TEST_APK" ]; then
TEST_APK=$(find "$PROJECT_DIR/android/app/build/outputs" -name "*.apk" -path "*androidTest*" 2>/dev/null | head -1)
fi
fi
if [ -z "$APP_APK" ] || [ -z "$TEST_APK" ]; then
echo "Error: Could not find APK files."
echo " App APK: ${APP_APK:-not found}"
echo " Test APK: ${TEST_APK:-not found}"
echo ""
echo "Build the APKs first:"
echo " ./gradlew assembleProdRelease assembleProdDebugAndroidTest"
exit 1
fi
echo "=========================================="
echo "Firebase Test Lab - Instrumentation Tests"
echo "=========================================="
echo "Project ID: $PROJECT_ID"
echo "App APK: $APP_APK"
echo "Test APK: $TEST_APK"
echo "Devices: ${#DEVICES[@]} configurations"
echo ""
# Build gcloud command
GCLOUD_CMD="gcloud firebase test android run \
--type instrumentation \
--project \"$PROJECT_ID\" \
--app \"$APP_APK\" \
--test \"$TEST_APK\" \
--timeout 60m \
--num-flaky-test-attempts 2 \
--record-video \
--performance-metrics \
--results-history-name \"Kordant Android Instrumentation Tests\""
# Add device configurations
for device in "${DEVICES[@]}"; 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
echo "Starting instrumentation tests..."
echo ""
eval "$GCLOUD_CMD"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo ""
echo "✅ Instrumentation tests completed successfully!"
echo "View results in Firebase Console: https://console.firebase.google.com/project/$PROJECT_ID/testlab"
else
echo ""
echo "❌ Instrumentation 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

View File

@@ -0,0 +1,118 @@
# Firebase Test Lab Device Matrix Configuration
# =============================================================================
# This file defines the device matrix for Firebase Test Lab test runs.
# Used by the gcloud CLI to specify which devices, orientations, and locales
# to test against.
#
# Usage:
# gcloud firebase test android run \
# --type <instrumentation|robo> \
# --app app/build/outputs/apk/prod/release/app-prod-release.apk \
# --test app/build/outputs/apk/androidTest/prod/debug/app-prod-debug-androidTest.apk \
# --device model=...,version=...,locale=...,orientation=...
#
# Reference: https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run
# =============================================================================
# Device matrix dimensions
# Each device runs with each orientation and locale combination
devices:
# Pixel 6 - Primary target device (API 33)
- model: Pixel6
version: 33
locales:
- en_US
- es_ES
orientations:
- portrait
- landscape
# Pixel 4 - Older Pixel device (API 30)
- model: Pixel4
version: 30
locales:
- en_US
- es_ES
orientations:
- portrait
- landscape
# Samsung Galaxy S21 - Popular Samsung device (API 31)
- model: GalaxyS21
version: 31
locales:
- en_US
- es_ES
orientations:
- portrait
- landscape
# Xiaomi Redmi Note 8 - Budget device (API 29)
- model: RedmiNote8
version: 29
locales:
- en_US
- es_ES
orientations:
- portrait
- landscape
# Low-end device - Minimum spec target (API 28, 2GB RAM equivalent)
- model: AquestM2
version: 28
locales:
- en_US
- es_ES
orientations:
- portrait
- landscape
# Robo test configuration
robo:
# Maximum time for robo crawl in seconds (default: 540s = 9min)
max_crawl_time: 600
# Number of steps for robo crawl (default: unlimited)
max_steps: 200
# App-specific login credentials for auto-login during crawl
# Credentials are stored securely in Cloud Key Management
# Set via environment variable: ROBO_SCRIPT_SOURCE
# Or provide a robo_script.json file for custom crawl paths
robo_script: robo_script.json
# Enable recording of test video
record_video: true
# Enable performance metrics collection
performance_metrics: true
# Number of test accounts to use (redundant sign-in handling)
# test_accounts:
# - username: ${ROBO_USERNAME}
# password: ${ROBO_PASSWORD}
# Instrumentation test configuration
instrumentation:
# Test runner class (AndroidJUnitRunner by default)
test_runner: androidx.test.runner.AndroidJUnitRunner
# Test APK to use
test_apk: app/build/outputs/apk/androidTest/prod/debug/app-prod-debug-androidTest.apk
# Test APK app APK
app_apk: app/build/outputs/apk/prod/release/app-prod-release.apk
# Enable recording of test video
record_video: true
# Enable performance metrics collection
performance_metrics: true
# Timeout per test in seconds (default: 300s = 5min)
test_timeout: 300
# Number of test shards (parallel execution across devices)
num_flaky_test_attempts: 2
# Fail fast - stop after first failure
fail_fast: false
# Results storage
results:
# Cloud Storage bucket for test results
# Format: gs://<project-id>-test-lab-<random-suffix>
# If not specified, Firebase creates one automatically
results_bucket: ""
# Directory within the bucket for results
results_dir: firebase-test-lab
# History name for grouping test runs in Firebase Console
history_name: "Kordant Android CI"