Skip to content

Commit 91ce213

Browse files
committed
Run Android UI tests via adb instrumentation
1 parent 4654849 commit 91ce213

File tree

1 file changed

+124
-91
lines changed

1 file changed

+124
-91
lines changed

scripts/build-android-app.sh

Lines changed: 124 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -571,30 +571,6 @@ log_instrumentation_state() {
571571
else
572572
ba_log "Package manager returned no packages on $EMULATOR_SERIAL"
573573
fi
574-
575-
local instrumentation_target instrumentation_line
576-
instrumentation_target=""
577-
if [ -n "$instrumentation_list" ]; then
578-
instrumentation_line="$(printf '%s\n' "$instrumentation_list" | awk -v pkg='${PACKAGE_NAME}.test' '$0 ~ pkg {print; exit}')"
579-
if [ -n "$instrumentation_line" ]; then
580-
instrumentation_target="${instrumentation_line#instrumentation:}"
581-
instrumentation_target="${instrumentation_target%% *}"
582-
else
583-
instrumentation_target="$(printf '%s\n' "$instrumentation_list" | awk -F' ' '/^instrumentation:/{print $1}' | head -n1)"
584-
instrumentation_target="${instrumentation_target#instrumentation:}"
585-
fi
586-
fi
587-
588-
if [ -n "$instrumentation_target" ] && [ "$have_test_apk" -eq 1 ]; then
589-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell am instrument -w -r \
590-
-e log true \
591-
"$instrumentation_target" \
592-
2>&1 | sed 's/^/[build-android-app] am instrument: /'
593-
elif [ -n "$instrumentation_target" ]; then
594-
ba_log "Instrumentation target $instrumentation_target available but test APK missing; skipping am instrument dry run"
595-
else
596-
ba_log "Skipping am instrument dry run; no instrumentation target detected on $EMULATOR_SERIAL"
597-
fi
598574
}
599575

600576
stop_emulator() {
@@ -735,92 +711,167 @@ fi
735711
"$ADB_BIN" -s "$EMULATOR_SERIAL" wait-for-device
736712
export ANDROID_SERIAL="$EMULATOR_SERIAL"
737713

738-
INSTALL_TIMEOUT_SECONDS="${INSTALL_TIMEOUT_SECONDS:-600}"
739-
if ! [[ "$INSTALL_TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || [ "$INSTALL_TIMEOUT_SECONDS" -le 0 ]; then
740-
INSTALL_TIMEOUT_SECONDS=600
714+
ASSEMBLE_TIMEOUT_SECONDS="${ASSEMBLE_TIMEOUT_SECONDS:-900}"
715+
if ! [[ "$ASSEMBLE_TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || [ "$ASSEMBLE_TIMEOUT_SECONDS" -le 0 ]; then
716+
ASSEMBLE_TIMEOUT_SECONDS=900
741717
fi
742718

743-
INSTALL_CMD=(
719+
GRADLE_ASSEMBLE_CMD=(
744720
"./gradlew"
745721
"--no-daemon"
746-
"installDebug"
747-
"installDebugAndroidTest"
722+
":app:assembleDebug"
723+
":app:assembleDebugAndroidTest"
724+
"-x"
725+
"lint"
726+
"-x"
727+
"test"
748728
)
749729
if command -v timeout >/dev/null 2>&1; then
750-
ba_log "Installing app and androidTest APKs with external timeout of ${INSTALL_TIMEOUT_SECONDS}s"
751-
INSTALL_CMD=("timeout" "$INSTALL_TIMEOUT_SECONDS" "${INSTALL_CMD[@]}")
730+
ba_log "Building app and androidTest APKs with external timeout of ${ASSEMBLE_TIMEOUT_SECONDS}s"
731+
GRADLE_ASSEMBLE_CMD=("timeout" "$ASSEMBLE_TIMEOUT_SECONDS" "${GRADLE_ASSEMBLE_CMD[@]}")
752732
else
753-
ba_log "timeout command not found; running install tasks without external watchdog"
733+
ba_log "timeout command not found; running Gradle assemble tasks without external watchdog"
754734
fi
755735

756-
GRADLE_INSTALL_LOG="$GRADLE_PROJECT_DIR/gradle-ui-install.log"
736+
GRADLE_ASSEMBLE_LOG="$GRADLE_PROJECT_DIR/gradle-ui-assemble.log"
757737
set +e
758738
(
759739
cd "$GRADLE_PROJECT_DIR"
760-
"${INSTALL_CMD[@]}" | tee "$GRADLE_INSTALL_LOG"
740+
"${GRADLE_ASSEMBLE_CMD[@]}" | tee "$GRADLE_ASSEMBLE_LOG"
761741
exit "${PIPESTATUS[0]}"
762742
)
763-
INSTALL_EXIT_CODE=$?
743+
ASSEMBLE_EXIT_CODE=$?
764744
set -e
765745

766-
if [ -f "$GRADLE_INSTALL_LOG" ]; then
767-
cp "$GRADLE_INSTALL_LOG" "$FINAL_ARTIFACT_DIR/ui-test-install.log"
768-
ba_log "Gradle install log saved to $FINAL_ARTIFACT_DIR/ui-test-install.log"
746+
if [ -f "$GRADLE_ASSEMBLE_LOG" ]; then
747+
cp "$GRADLE_ASSEMBLE_LOG" "$FINAL_ARTIFACT_DIR/ui-test-assemble.log"
748+
ba_log "Gradle assemble log saved to $FINAL_ARTIFACT_DIR/ui-test-assemble.log"
749+
fi
750+
751+
if [ "$ASSEMBLE_EXIT_CODE" -ne 0 ]; then
752+
ba_log "Gradle assemble tasks exited with status $ASSEMBLE_EXIT_CODE"
753+
stop_emulator
754+
exit 1
755+
fi
756+
757+
APP_APK="$(find "$GRADLE_PROJECT_DIR/app/build/outputs/apk/debug" -maxdepth 1 -name '*-debug.apk' | head -n1 || true)"
758+
TEST_APK="$(find "$GRADLE_PROJECT_DIR/app/build/outputs/apk/androidTest/debug" -maxdepth 1 -name '*-debug-androidTest.apk' | head -n1 || true)"
759+
760+
if [ -z "$APP_APK" ] || [ ! -f "$APP_APK" ]; then
761+
ba_log "App APK not found after assemble tasks" >&2
762+
stop_emulator
763+
exit 1
764+
fi
765+
if [ -z "$TEST_APK" ] || [ ! -f "$TEST_APK" ]; then
766+
ba_log "androidTest APK not found after assemble tasks" >&2
767+
stop_emulator
768+
exit 1
769+
fi
770+
771+
adb_install_retry() {
772+
local serial="$1" apk="$2" tries=5
773+
local attempt
774+
for attempt in $(seq 1 "$tries"); do
775+
if command -v timeout >/dev/null 2>&1; then
776+
timeout 120 "$ADB_BIN" -s "$serial" install -r -t "$apk" && return 0
777+
else
778+
"$ADB_BIN" -s "$serial" install -r -t "$apk" && return 0
779+
fi
780+
if [ "$attempt" -lt "$tries" ]; then
781+
ba_log "install retry $attempt/$tries for $(basename "$apk")"
782+
"$ADB_BIN" -s "$serial" wait-for-device
783+
sleep 3
784+
fi
785+
done
786+
return 1
787+
}
788+
789+
ba_log "Installing app APK: $APP_APK"
790+
if ! adb_install_retry "$EMULATOR_SERIAL" "$APP_APK"; then
791+
dump_emulator_diagnostics
792+
stop_emulator
793+
exit 1
769794
fi
770795

771-
if [ "$INSTALL_EXIT_CODE" -ne 0 ]; then
772-
ba_log "Gradle install tasks exited with status $INSTALL_EXIT_CODE"
796+
ba_log "Installing androidTest APK: $TEST_APK"
797+
if ! adb_install_retry "$EMULATOR_SERIAL" "$TEST_APK"; then
798+
dump_emulator_diagnostics
773799
stop_emulator
774800
exit 1
775801
fi
776802

803+
APP_PACKAGE_PATH="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path "$PACKAGE_NAME" 2>/dev/null | tr -d '\r' || true)"
804+
if [ -n "$APP_PACKAGE_PATH" ]; then
805+
printf '%s\n' "$APP_PACKAGE_PATH" | sed 's/^/[build-android-app] app-apk: /'
806+
else
807+
ba_log "App package $PACKAGE_NAME not yet reported by pm path on $EMULATOR_SERIAL"
808+
fi
809+
810+
TEST_PACKAGE_PATH="$("$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm path "${PACKAGE_NAME}.test" 2>/dev/null | tr -d '\r' || true)"
811+
if [ -n "$TEST_PACKAGE_PATH" ]; then
812+
printf '%s\n' "$TEST_PACKAGE_PATH" | sed 's/^/[build-android-app] test-apk: /'
813+
else
814+
ba_log "Test package ${PACKAGE_NAME}.test not yet reported by pm path on $EMULATOR_SERIAL"
815+
fi
816+
777817
log_instrumentation_state
778818

779-
"$ADB_BIN" kill-server >/dev/null 2>&1 || true
780-
"$ADB_BIN" start-server >/dev/null 2>&1 || true
781-
"$ADB_BIN" -s "$EMULATOR_SERIAL" wait-for-device
782-
export ANDROID_SERIAL="$EMULATOR_SERIAL"
819+
RUNNER="$(
820+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list instrumentation \
821+
| awk -v pkg="${PACKAGE_NAME}" '$1=="instrumentation:" && $0 ~ ("target=" pkg) {print $2; exit}'
822+
)"
823+
if [ -z "$RUNNER" ]; then
824+
RUNNER="$(
825+
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell pm list instrumentation \
826+
| awk '$1=="instrumentation:" {print $2; exit}'
827+
)"
828+
fi
829+
RUNNER="${RUNNER//$'\r'/}"
830+
RUNNER="${RUNNER//$'\n'/}"
831+
832+
if [ -z "$RUNNER" ]; then
833+
ba_log "No instrumentation runner found for $PACKAGE_NAME"
834+
dump_emulator_diagnostics
835+
stop_emulator
836+
exit 1
837+
fi
783838

784839
UI_TEST_TIMEOUT_SECONDS="${UI_TEST_TIMEOUT_SECONDS:-900}"
785840
if ! [[ "$UI_TEST_TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || [ "$UI_TEST_TIMEOUT_SECONDS" -le 0 ]; then
786841
ba_log "Invalid UI_TEST_TIMEOUT_SECONDS=$UI_TEST_TIMEOUT_SECONDS provided; falling back to 900"
787842
UI_TEST_TIMEOUT_SECONDS=900
788843
fi
789844

790-
GRADLE_TEST_CMD=(
791-
"./gradlew"
792-
"--no-daemon"
793-
"-Pandroid.testInstrumentationRunnerArguments=class=${PACKAGE_NAME}.${MAIN_NAME}UiTest"
794-
"connectedDebugAndroidTest"
845+
INSTRUMENT_ARGS=(
846+
"-w"
847+
"-r"
848+
"-e"
849+
"log"
850+
"true"
851+
"-e"
852+
"clearPackageData"
853+
"true"
854+
"-e"
855+
"class"
856+
"${PACKAGE_NAME}.${MAIN_NAME}UiTest"
795857
)
858+
INSTRUMENT_CMD=("$ADB_BIN" "-s" "$EMULATOR_SERIAL" "shell" "am" "instrument" "${INSTRUMENT_ARGS[@]}" "$RUNNER")
796859
if command -v timeout >/dev/null 2>&1; then
797-
ba_log "Running instrumentation UI tests with external timeout of ${UI_TEST_TIMEOUT_SECONDS}s"
798-
GRADLE_TEST_CMD=("timeout" "$UI_TEST_TIMEOUT_SECONDS" "${GRADLE_TEST_CMD[@]}")
860+
ba_log "Running instrumentation via am instrument with external timeout of ${UI_TEST_TIMEOUT_SECONDS}s"
861+
INSTRUMENT_CMD=("timeout" "$UI_TEST_TIMEOUT_SECONDS" "${INSTRUMENT_CMD[@]}")
799862
else
800-
ba_log "timeout command not found; running instrumentation tests without external watchdog"
863+
ba_log "timeout command not found; running instrumentation without external watchdog"
801864
fi
802865

803-
GRADLE_UI_TEST_LOG="$GRADLE_PROJECT_DIR/gradle-ui-test.log"
804-
ba_log "Streaming Gradle UI test output (also saved to $GRADLE_UI_TEST_LOG)"
805-
866+
INSTRUMENT_LOG="$FINAL_ARTIFACT_DIR/ui-test-instrumentation.log"
806867
set +e
807-
(
808-
cd "$GRADLE_PROJECT_DIR"
809-
"${GRADLE_TEST_CMD[@]}" | tee "$GRADLE_UI_TEST_LOG"
810-
exit "${PIPESTATUS[0]}"
811-
)
812-
TEST_EXIT_CODE=$?
868+
"${INSTRUMENT_CMD[@]}" | tee "$INSTRUMENT_LOG"
869+
INSTRUMENT_EXIT_CODE=${PIPESTATUS[0]}
813870
set -e
814871

815-
if [ -f "$GRADLE_UI_TEST_LOG" ]; then
816-
cp "$GRADLE_UI_TEST_LOG" "$FINAL_ARTIFACT_DIR/ui-test-gradle.log"
817-
ba_log "Gradle UI test log saved to $FINAL_ARTIFACT_DIR/ui-test-gradle.log"
818-
fi
819-
820-
if [ "$TEST_EXIT_CODE" -eq 124 ]; then
821-
ba_log "Instrumentation tests exceeded ${UI_TEST_TIMEOUT_SECONDS}s timeout and were terminated"
822-
elif [ "$TEST_EXIT_CODE" -ne 0 ]; then
823-
ba_log "Instrumentation tests exited with status $TEST_EXIT_CODE"
872+
if [ "$INSTRUMENT_EXIT_CODE" -ne 0 ]; then
873+
ba_log "Instrumentation command exited with status $INSTRUMENT_EXIT_CODE"
874+
dump_emulator_diagnostics
824875
fi
825876

826877
copy_device_file() {
@@ -875,15 +926,6 @@ if [ -f "$EMULATOR_LOG" ]; then
875926
cp "$EMULATOR_LOG" "$FINAL_ARTIFACT_DIR/emulator.log" || true
876927
fi
877928

878-
TEST_RESULT_DIR="$APP_MODULE_DIR/build/outputs/androidTest-results/connected"
879-
if [ -d "$TEST_RESULT_DIR" ]; then
880-
RESULT_DEST="$FINAL_ARTIFACT_DIR/androidTest-results"
881-
rm -rf "$RESULT_DEST"
882-
mkdir -p "$RESULT_DEST"
883-
cp -R "$TEST_RESULT_DIR/." "$RESULT_DEST/"
884-
ba_log "Android test results copied to $RESULT_DEST"
885-
fi
886-
887929
if [ -n "${GITHUB_ENV:-}" ]; then
888930
if [ -n "$DEFAULT_SCREENSHOT" ]; then
889931
printf 'CN1_UI_TEST_SCREENSHOT=%s\n' "$DEFAULT_SCREENSHOT" >> "$GITHUB_ENV"
@@ -896,22 +938,13 @@ if [ -n "${GITHUB_ENV:-}" ]; then
896938
fi
897939
fi
898940

899-
if [ "$TEST_EXIT_CODE" -eq 0 ]; then
900-
(
901-
cd "$GRADLE_PROJECT_DIR"
902-
./gradlew --no-daemon assembleDebug
903-
)
904-
else
905-
ba_log "Instrumentation tests failed (exit code $TEST_EXIT_CODE); skipping assembleDebug"
906-
fi
907-
908941
export JAVA_HOME="$ORIGINAL_JAVA_HOME"
909942

910943
stop_emulator
911944
trap - EXIT
912945

913-
if [ "$TEST_EXIT_CODE" -ne 0 ]; then
914-
exit "$TEST_EXIT_CODE"
946+
if [ "$INSTRUMENT_EXIT_CODE" -ne 0 ]; then
947+
exit "$INSTRUMENT_EXIT_CODE"
915948
fi
916949

917950
if [ "$SCREENSHOT_STATUS" -ne 0 ]; then

0 commit comments

Comments
 (0)