Skip to content

Fixing BCIT and in app tests in CI #406

Fixing BCIT and in app tests in CI

Fixing BCIT and in app tests in CI #406

name: In-App Message E2E Tests
on:
push:
branches: [ InApp-Display-E2E ]
pull_request:
branches: [ InApp-Display-E2E, master, develop ]
workflow_dispatch: # Allow manual triggering
jobs:
inapp-e2e-tests:
name: In-App Message E2E Tests
runs-on: macos-15-intel
strategy:
matrix:
api-level: [34] # MVP testing on most relevant API level only
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Set up Android SDK
uses: android-actions/setup-android@v2
- name: Create local.properties
run: |
echo "sdk.dir=$ANDROID_SDK_ROOT" > local.properties
echo "ndk.dir=$ANDROID_SDK_ROOT/ndk" >> local.properties
- name: Accept Android SDK Licenses
run: |
echo "Accepting Android SDK licenses..."
yes | sdkmanager --licenses || true
echo "SDK licenses accepted"
- name: Setup Google Services Configuration
run: |
echo "Setting up Google Services configuration for CI..."
# Ensure the google-services.json file exists for the build
if [ ! -f "integration-tests/google-services.json" ]; then
echo "Creating google-services.json from template..."
cp integration-tests/google-services.json.template integration-tests/google-services.json
fi
echo "Google Services configuration ready"
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Pre-download Gradle and Build (Parallel with Emulator)
run: |
echo "Pre-downloading Gradle and building while emulator boots..."
# Download Gradle wrapper in background
./gradlew --version &
# Start building APKs in background
./gradlew :integration-tests:assembleDebug :integration-tests:assembleDebugAndroidTest --no-daemon &
echo "Build started in background..."
- name: Run UI Tests with Emulator (Intel / x86_64)
uses: ReactiveCircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
target: google_apis
arch: x86_64
profile: pixel_6
cores: 2
ram-size: 3072M
heap-size: 576M
force-avd-creation: true
disable-animations: true
emulator-boot-timeout: 900
emulator-options: -no-window -no-snapshot -gpu swiftshader_indirect -no-boot-anim -camera-back none -partition-size 6000
pre-emulator-launch-script: |
# Clean + start adb after platform-tools exist (avoids tcp:5037 noise)
adb kill-server >/dev/null 2>&1 || true
adb start-server
script: |
# SDK-170 OBSERVABILITY: capture diagnostics that survive the action exit.
# The android-emulator-runner kills the emulator on its way out, so any
# adb-dependent capture MUST happen before this script returns. We write
# everything under $GITHUB_WORKSPACE so a later step can upload it.
DIAG_DIR="$GITHUB_WORKSPACE/integration-tests/build/diagnostics"
mkdir -p "$DIAG_DIR"
capture_diag() {
local label="$1"
local prefix="$2"
echo "=== diag capture: $label ==="
{
echo "# label: $label"
echo "# t: $(date -u +%FT%TZ)"
echo
echo "## adb devices"
adb devices 2>&1
echo
echo "## top activities"
adb shell dumpsys activity activities 2>&1 | head -200
echo
echo "## window state (focused app + visible windows)"
adb shell dumpsys window 2>&1 | head -200
echo
echo "## connectivity (active default network, link addresses, dns)"
adb shell dumpsys connectivity 2>&1 | head -120
echo
echo "## meminfo (system_server + integration tests)"
adb shell dumpsys meminfo 2>&1 | head -80
echo
echo "## installed iterable packages"
adb shell pm list packages 2>&1 | grep iterable || true
echo
echo "## boot props"
adb shell getprop sys.boot_completed dev.bootcomplete init.svc.netd net.dns1 ro.build.version.release ro.build.version.sdk 2>&1 | head -10
} > "$DIAG_DIR/${prefix}-state.txt" 2>&1
# UiAutomator hierarchy and screenshot — the smoking gun for "button not found"
adb shell uiautomator dump /sdcard/hierarchy.xml >/dev/null 2>&1 || true
adb pull /sdcard/hierarchy.xml "$DIAG_DIR/${prefix}-hierarchy.xml" >/dev/null 2>&1 || echo "(no hierarchy)"
adb shell screencap -p /sdcard/screenshot.png >/dev/null 2>&1 || true
adb pull /sdcard/screenshot.png "$DIAG_DIR/${prefix}-screenshot.png" >/dev/null 2>&1 || echo "(no screenshot)"
}
echo "Emulator is ready! Running tests..."
echo "Setting up permissions..."
adb shell pm grant com.iterable.integration.tests android.permission.POST_NOTIFICATIONS || true
adb shell pm grant com.iterable.integration.tests android.permission.INTERNET || true
adb shell pm grant com.iterable.integration.tests android.permission.ACCESS_NETWORK_STATE || true
adb shell pm grant com.iterable.integration.tests android.permission.WAKE_LOCK || true
echo "Running In-App Message MVP test..."
echo "Debug: Checking if APKs are ready..."
ls -la integration-tests/build/outputs/apk/ || echo "APK directory not found"
echo "Debug: Verifying API keys are set..."
echo "ITERABLE_API_KEY length: ${#ITERABLE_API_KEY}"
echo "ITERABLE_SERVER_API_KEY length: ${#ITERABLE_SERVER_API_KEY}"
echo "ITERABLE_TEST_USER_EMAIL: $ITERABLE_TEST_USER_EMAIL"
# Snapshot pre-test device state. If tests fail because the activity never
# foregrounded, this captures what was on screen *before* we even ran.
capture_diag "pre-test" "00-pre-test"
# Stream full logcat to the workspace so we get an artifact even on success.
adb logcat -c >/dev/null 2>&1 || true
adb logcat > "$DIAG_DIR/10-logcat-full.txt" &
LOGCAT_PID=$!
GRADLE_EXIT=0
./gradlew :integration-tests:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.class=com.iterable.integration.tests.InAppMessageIntegrationTest#testInAppMessageMVP \
--stacktrace --no-daemon || GRADLE_EXIT=$?
# Stop logcat ASAP so post-test capture isn't entangled with it.
kill $LOGCAT_PID 2>/dev/null || true
wait $LOGCAT_PID 2>/dev/null || true
# Always capture post-test state — useful on success too (proves the test
# really did exercise the SDK and surface campaigns).
capture_diag "post-test" "20-post-test"
# Filtered logcat for fast triage; full logcat is also uploaded.
grep -E 'IterableApi|IterableRequest|IterableInApp|IterableEmbedded|IntegrationMainActivity|BaseIntegrationTest|InAppMessageIntegrationTest|PushNotificationIntegrationTest|EmbeddedMessageIntegrationTest|DeepLinkIntegrationTest|FATAL|AndroidRuntime|ANR' \
"$DIAG_DIR/10-logcat-full.txt" > "$DIAG_DIR/11-logcat-filtered.txt" 2>/dev/null || true
echo
echo "=== diagnostics summary ==="
ls -la "$DIAG_DIR"
echo
echo "Last 50 logcat lines (full file uploaded as artifact):"
tail -50 "$DIAG_DIR/10-logcat-full.txt" || true
if [ "$GRADLE_EXIT" != "0" ]; then
echo "::error::Test gradle task failed with exit code $GRADLE_EXIT — see e2e-diagnostics-api-${{ matrix.api-level }} artifact"
exit "$GRADLE_EXIT"
fi
env:
ITERABLE_API_KEY: ${{ secrets.BCIT_ITERABLE_API_KEY }}
ITERABLE_SERVER_API_KEY: ${{ secrets.BCIT_ITERABLE_SERVER_API_KEY }}
ITERABLE_TEST_USER_EMAIL: ${{ secrets.BCIT_ITERABLE_TEST_USER_EMAIL }}
- name: Upload E2E diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-diagnostics-api-${{ matrix.api-level }}
path: |
integration-tests/build/diagnostics/
integration-tests/build/reports/
integration-tests/build/outputs/
if-no-files-found: warn
retention-days: 7
# test-summary:
# name: Test Summary
# runs-on: ubuntu-latest
# needs: inapp-e2e-tests
# if: always()
# steps:
# - name: Checkout code
# uses: actions/checkout@v4
# - name: Download Test Results
# uses: actions/download-artifact@v4
# with:
# name: inapp-e2e-test-results-api-34
# path: test-results/
# - name: Generate Test Summary
# run: |
# echo "## In-App Message E2E Test Results" >> $GITHUB_STEP_SUMMARY
# echo "" >> $GITHUB_STEP_SUMMARY
# echo "### Test Execution Summary" >> $GITHUB_STEP_SUMMARY
# echo "- **Branch**: InApp-Display-E2E" >> $GITHUB_STEP_SUMMARY
# echo "- **API Level Tested**: 34" >> $GITHUB_STEP_SUMMARY
# echo "- **Test Method**: testInAppMessageMVP" >> $GITHUB_STEP_SUMMARY
# echo "- **Test Type**: E2E Integration Test" >> $GITHUB_STEP_SUMMARY
# echo "" >> $GITHUB_STEP_SUMMARY
# echo "### E2E Test Scenarios" >> $GITHUB_STEP_SUMMARY
# echo "- ✅ User Sign-in Verification" >> $GITHUB_STEP_SUMMARY
# echo "- ✅ In-App Message Trigger" >> $GITHUB_STEP_SUMMARY
# echo "- ✅ Message Display Verification" >> $GITHUB_STEP_SUMMARY
# echo "- ✅ Button Click Interaction" >> $GITHUB_STEP_SUMMARY
# echo "- ✅ Message Dismissal" >> $GITHUB_STEP_SUMMARY
# echo "" >> $GITHUB_STEP_SUMMARY
# echo "### Artifacts Available" >> $GITHUB_STEP_SUMMARY
# echo "- Test execution reports" >> $GITHUB_STEP_SUMMARY
# echo "- Code coverage reports" >> $GITHUB_STEP_SUMMARY
# echo "- Debug screenshots" >> $GITHUB_STEP_SUMMARY
# echo "- Detailed test logs" >> $GITHUB_STEP_SUMMARY