taler-monitoring/android-test/GUI-AUTOMATION-NOTES.md
2026-07-18 13:56:54 +02:00

18 KiB
Raw Blame History

GUI automation notes (Android wallet)

Canonical notes for graphical Android wallet tests against GOA / stage.


Minimal variant (implemented first) — status 2026-07

This is the minimal vanilla path we actually shipped; full dual-platform GUI is planned via flags (below), not required to use these scripts today.

Piece Status Notes
F-Droid published APK install done net.taler.wallet.fdroid 1.6.1 / 854
Source build + same smoke done :wallet:assembleFdroidDebugnet.taler.wallet.fdroid.debug
Default source branch done dev/hernani-inference/fix-bank-withdraw-auto-exchange (minimal GOA exchange auto-add)
Deep-link entry (≡ QR) done adb VIEW withdraw then pay (taler://withdraw/…taler://pay…)
Explorer API mint (chain) done run-goa-gui-chain.sh (GOA + stage)
UI taps via uiautomator done best-effort Confirm/ToS/Pay; ANR → prefer Wait
Screenshots / logcat artifacts done under out*, out-gui-chain/ (gitignored)
Host CLI e2e settlement separate taler-monitoring.sh e2e / ladder (not Android UI)
Reliable unattended Confirm on 4GiB Linux host limited System UI ANR; use phone or more RAM
iOS GUI not in this tree see taler-ios dev/hernani-inference/gui-workflows
macOS full dual AVD helpers upstream taler-android gui-workflows (Homebrew); ported ideas here for Linux

Ground rule: bring it to run; app diffs only if needed and minimal; prefer extending existing dev/hernani-inference/* branches over new trees.

Minimalvariante: was geht / was nicht

Einschränkungen der aktuell implementierten Minimalvariante (deep-link + uiautomator best-effort). Kein voller Dual-Platform-GUI-Stack, kein Ersatz für Host-CLI-Settlement.

Geht (grün)

Fähigkeit Wie / Hinweis
APK installieren F-Droid net.taler.wallet.fdroid oder Source assembleFdroidDebug (.debug)
GOA-Exchange ohne manuelles Add Source-Build von fix-bank-withdraw-auto-exchange (Default in run-android-build-and-smoke.sh)
Abheben + Bezahlen Beide Beine: erst Withdraw-URI + Taps, dann Pay-URI + Taps (DO_WITHDRAW/DO_PAY)
Light UI-Drive Confirm / Accept / Pay-Taps über Label-Suche (lib_ui.py, gui-smoke, chain)
Multi-Runden-Taps run-android-gui-smoke.sh / run-goa-gui-chain.sh (best-effort)
Explorer-Mint (Kette) run-goa-gui-chain.sh + EXP_PW_FILE (GOA + stage)
Stack-Wahl STACK=goa / stage (Bank/Merchant-URLs)
Artefakte Screenshots, UI-XML, logcat unter out* / out-gui-chain/ (gitignored)
Hybrid-Smoke Install + Intent + leichte Taps: run-android-pay-smoke.sh
Settlement nachweisen Host-seitig: taler-monitoring.sh e2e / ladder (nicht Android-UI)
Flags abschalten AUTO_ANDROID=0 skip; AUTO_GUI=0 → nur deep-link/pay-smoke

Geht nicht oder nur eingeschränkt (rot / gelb)

Beschränkung Folge / Workaround
Unattended Confirm → settled im Emulator (~4GiB Host) Häufig System UI ANR; Taps bleiben hängen. Prefer Wait auf ANR-Dialog, echtes Gerät, oder Host mit mehr RAM. Kein zuverlässiges grünes E2E nur über GUI auf dem schwachen Emulator.
Vollständige Wallet-Settlement-Assertion in der GUI Minimalvariante prüft nicht „Balance final / transfer_done“ in der App-Oberfläche. Proof bleibt CLI/e2e.
Kamera / physischer QR-Scan Absichtlich nicht automatisiert; deep-link ist der Shortcut. Landing-QR-Pfade sind HTTP-Thema, nicht Android-GUI.
Browser-Shop-Checkout-UI Kein Chromium/WebView-Drive; Pay-URI kommt per Template-POST + Intent.
Volles ToS-Scroll / alle Dialoge Best-effort Accept-Tap; lange ToS oder unerwartete Sheets können hängen bleiben.
Published F-Droid allein auf GOA Kann Exchange-Add / Spinner-Probleme zeigen → fix-branch-APK bauen; bei Spinner-Hang optional fix-withdraw-spinner-fallback.
iOS-GUI Nicht in diesem Tree; siehe taler-ios gui-workflows.
macOS dual AVD / Homebrew-Helpers Upstream gui-workflows; hier nur Linux-taugliche Port-Ideen.
AUTO_* in jedem Script erzwungen Design + teilweise verdrahtet; Wrapper-Checkliste noch offen.
run-until-done / CLI-Wallet in GUI-Skripten Gehört zu CLI-Automation, nicht GUI; siehe CLI-AUTOMATION-NOTES.md.
CI grün = „User hat bezahlt“ Smoke = Intent + best-effort UI. Wirtschaftlicher Erfolg = Host-e2e / ladder / Explorer.

Erwartetes Ergebnis pro Schicht

Schicht Erfolgskriterium Minimalvariante
A Install APK installed, App startet
B Deep-link Intent delivered, Wallet öffnet Withdraw/Pay-Flow
C GUI taps Dump+Tap ohne Crash; ANR ggf. mit Wait; kein Garant für „Paid“
D Evidence Artefakte geschrieben
Settlement Außerhalb GUI: Host e2e/ladder

Wann Minimalvariante reicht

  • Smoke nach APK-/Branch-Build (Intent kommt an, App crasht nicht).
  • Manuelle Nacharbeit am Gerät nach vorbereiteten URIs.
  • GOA/stage Erreichbarkeit von Landing/Template + Wallet-Einstieg.

Wann nicht reicht → nächster Schritt

  • Unattended grünes Pay-E2E auf dem Emulator → mehr RAM / physisches Gerät, ggf. fix-withdraw-spinner-fallback.
  • Beweis „Münzen da / Merchant paid“ → CLI e2e/ladder, nicht GUI-smoke.
  • iOS / Dual-Platform → andere Repos/Flags, nicht diese Skripte.
cd scripts/taler-monitoring/android-test

# Minimal hybrid (install + deep-link + light taps)
STACK=goa ./run-android-pay-smoke.sh

# GUI multi-round taps
STACK=goa ./run-android-gui-smoke.sh
STACK=stage ./run-android-gui-smoke.sh

# Explorer mint + multi withdraw/pay chain (from gui-workflows)
EXP_PW_FILE=$HOME/src/koopa/koopa-admin-secrets/koopa/host-root/taler-bank/bank-explorer-password.txt \
  STACK=goa PKG=net.taler.wallet.fdroid.debug \
  ./run-goa-gui-chain.sh

# Build fix-branch APK then smoke (GUI=1 for gui smoke)
./run-android-build-and-smoke.sh
GUI=1 ./run-android-build-and-smoke.sh

Platform capability flags (planned + defaults)

Automation can run on hosts that support Android only, GUI tooling only (conceptual), or both. Flags keep that explicit for CI and laptops.

Proposed env flags

Variable Values Meaning
AUTO_ANDROID 0 / 1 Run Android wallet automation (adb, APK, emulator/device)
AUTO_GUI 0 / 1 Drive graphical UI (uiautomator taps, multi-round). If 0, deep-link/CLI-only install smoke.
AUTO_PLATFORM auto / linux / macos / ios Host family (optional override)
EMULATOR_HEADLESS 1 (default) / 0 No host window (-no-window). Server/CI-safe.
WINDOWED 0 / 1 Shortcut: WINDOWED=1 ⇒ show emulator window (EMULATOR_HEADLESS=0)
EMULATOR_GPU default swiftshader_indirect Guest GLES still runs headless (layout/taps/screenshots). Override host only if windowed + real GPU.
AUTO_START_EMULATOR 1 (default) / 0 If no adb device, start AVD via start-android-emulator.sh --wait

Headless mode (default)

Default for all GUI / pay smokes: no window on the host. Opening an emulator GUI on servers (or headless CI) is wrong; these scripts therefore start the AVD with -no-window and still keep graphics logic in the guest:

Piece Headless default
Host window off (-no-window, QT_QPA_PLATFORM=offscreen, no DISPLAY)
Guest GLES on via SwiftShader (-gpu swiftshader_indirect)
UI automation onuiautomator dump/tap + screencap (no X11 needed)
Audio / boot anim off (-no-audio -no-boot-anim)
# explicit (same as default)
./start-android-emulator.sh --wait

# or let smoke auto-start headless AVD when no phone is plugged in
STACK=goa ./run-android-gui-smoke.sh

# laptop: show the emulator window
WINDOWED=1 ./start-android-emulator.sh --wait
# or: EMULATOR_HEADLESS=0 EMULATOR_GPU=host ./start-android-emulator.sh --wait

Shared code: lib_android_env.sh + start-android-emulator.sh.

Semantics:

AUTO_ANDROID AUTO_GUI Behaviour
1 0 Android install + deep-link smoke only (no multi-round taps)
1 1 Android + graphical drive (vanilla GUI / chain)
0 1 Reserved (e.g. future desktop/web GUI); currently no-op with a clear message
0 0 Skip mobile automation

Defaults by host (when flags unset)

Host (uname -s) Default AUTO_ANDROID Default AUTO_GUI Rationale
Linux 1 1 if device/emulator present, else scripts exit 3 This repos day-to-day path; Android only (no iOS here)
Darwin (macOS) 1 1 Can run Android emulators and (separately) taler-ios GUI helpers; both flags on for Android scripts; iOS is out of tree
Other 0 0 Fail closed

Linux default = Android (no second mobile platform in this suite).
macOS may enable both ecosystems in the wider monorepo sense; for these scripts only Android is implemented — set AUTO_ANDROID=1 (default) and keep iOS under taler-ios.

Resolution helper (convention for future wrappers)

# Example for a future run-all-mobile.sh
os=$(uname -s)
: "${AUTO_PLATFORM:=auto}"
case "$AUTO_PLATFORM" in
  auto) case "$os" in Linux) AUTO_PLATFORM=linux ;; Darwin) AUTO_PLATFORM=macos ;; *) AUTO_PLATFORM=other ;; esac ;;
esac
case "$AUTO_PLATFORM" in
  linux)
    : "${AUTO_ANDROID:=1}"
    : "${AUTO_GUI:=1}"
    # no iOS
    ;;
  macos)
    : "${AUTO_ANDROID:=1}"
    : "${AUTO_GUI:=1}"
    # optional later: AUTO_IOS=1 for taler-ios scripts
    ;;
  *)
    : "${AUTO_ANDROID:=0}"
    : "${AUTO_GUI:=0}"
    ;;
esac

Scripts today implement Android only; they should honour:

  • AUTO_ANDROID=0 → exit 0 with “skipped (AUTO_ANDROID=0)”
  • AUTO_GUI=0 → call deep-link smoke without multi-round GUI (or set GUI_ROUNDS=0)

Vanilla layers (detail)

Layer What Tooling
A — Install F-Droid or from-source APK adb install
B — Entry (shortcut) taler://withdraw/… / taler://pay… adb am start -a VIEW
C — Graphical UI Confirm / ToS / Pay taps; ANR Wait uiautomator + lib_ui.py / chain
D — Evidence Screenshots, XML, logcat, URIs out*/

Legitimate shortcuts

Shortcut Replaces
Deep-link withdraw/pay Camera QR / opening paywall
Host POST template → pay URI Browser shop checkout UI
Label-list taps Human reading button text
Skip full ToS scroll Tap Accept if shown

Scripts

Script Role
run-android-pay-smoke.sh Hybrid: install + deep-link + light taps
run-android-gui-smoke.sh Multi-round GUI drive
run-goa-gui-chain.sh Multi mint/withdraw/pay (gui-workflows port)
run-android-build-and-smoke.sh Build git ref (branch/tag) + smoke (GUI=1 optional)
run-android-variant-matrix.sh published + stable-self + master (compare builds)
start-android-emulator.sh Start AVD (headless default, SwiftShader)
lib_android_env.sh Flags, PATH, android_ensure_device
lib_ui.py Dump/tap/ANR helpers

Build variants (anti“weird local build”)

Variant Source Severity Purpose
stable-self only rebuild of current stable tag WARN Self-build vs published for one release
published F-Droid current APK ≤14d → BLOCKER, else WARN What users install
older / milestones F-Droid APK ~3 / 6 / 9 / 12 mo always WARN No self-build of old tags
master origin/master rebuild WARN Tip — never hard-blocks
fix (optional) inference branch soft GOA automation fixes

Self-build: current stable only (plus master/fix if requested) — not older releases.
Blocker window: releases ≤ 14 days.
Milestones: nearest tags to 90/180/270/365d with a still-hosted F-Droid APK.


Stacks under test

Stack Withdraw Pay
GOA explorer mint / demo-withdraw.json @ bank.hacktivism.ch goa-shop templates / Paivana pay-template
stage explorer / demo-withdraw @ stage.bank… fermes / jardin public templates

Lageübersicht GOA + stage (as-is survey · 2026-07-17 ~22:0522:18)

Device: headless emulator-5554 · host ~3.7GiB RAM (often <300MiB free) · timeout per leg ≤420s.
Legs: Abheben + Bezahlen (DO_WITHDRAW=1 DO_PAY=1). Artefakte: out-survey-20260717-220527/ (gitignored).

Varianten

Variante Quelle Bemerkung
stable (published) F-Droid net.taler.wallet.fdroid 1.6.1 / 854 as-is
master as-is rebuild origin/master @ f65a976c.fdroid.debug as-is, no patches
ältere Releases (3/6/9/12 mon) F-Droid APKs für 1.5.0/1.3.0/1.1.0/1.0.8 nicht auffindbar (HTTP miss) → SKIP (kein Selbstbau älterer Tags)
master + inference (extra) local branch local/master-with-inference @ 3ebe8b09 merges fix-bank-withdraw-auto-exchange + fix-withdraw-spinner-fallback · not pushed

Ergebnis-Matrix

Variant Stack Install / deep-link Withdraw URI Pay URI wallet-core Abheben wallet-core Pay ANR Exit
stable published goa (hacktivism) OK OK bank.hacktivism.ch OK paivana template NO soft/YES once* YES 10
stable published stage (*.lefrancpaysan) OK OK stage.bank… OK fermes order NO NO YES 10
master as-is goa OK OK OK paivana NO NO YES 10
master as-is stage OK OK OK fermes NO NO YES 10
master+inference goa OK OK OK NO NO YES 10
master+inference stage OK OK OK NO NO YES 10

*stable-goa console once reported pay wallet-core YES mid-run; final score still ANR-dominated / not reliable settlement.

Was pro Stack steht (Infra)

Check goa / hacktivism stage / *.lefrancpaysan
Bank …/intro/demo-withdraw.jsontaler://withdraw/… OK OK
Pay entry paivana pay-template OK fermes panier-legumes POST → taler://pay/… OK
adb VIEW Intent delivery OK OK
Unattended Confirm/Abheben/Pay GUI FAIL (ANR) FAIL (ANR)
wallet-core prepare/accept withdraw in logcat not seen not seen

Fazit as-is: Beide Stacks liefern die Eingänge (Withdraw- + Pay-URIs). Die GUI/wallet-core-Strecke ist auf diesem Emulator für alle getesteten App-Varianten (stable, master, inference) gleich tot — System UI / Android System ANR, keine brauchbaren Taps. Das ist kein Stack-Unterschied GOA vs stage und kein belastbarer App-Versions-Vergleich.

Inference-Patch-Versuch (lokal, kein Push)

Weil nichts der as-is-Varianten wallet-core-grün war, wurde zusätzlich gebaut:

taler-android branch: local/master-with-inference   # NOT pushed
base:     origin/master
merged:   origin/dev/hernani-inference/fix-bank-withdraw-auto-exchange
          origin/dev/hernani-inference/fix-withdraw-spinner-fallback
commit:   3ebe8b091379
APK:      apks/wallet-master-inference-3ebe8b091379.apk (local)
Stack Inference smoke Besser als master/stable?
goa exit 10, ANR, no withdraw core Nein
stage exit 10, ANR, no withdraw core Nein

Kein grünes Inference-Signal auf diesem Host → wir können nicht belegen, dass die Patches Withdraw/Pay „retten“.
Ebenso können wir nicht belegen, dass master ohne Patches „schuld“ ist: die Umgebung erreicht wallet-core gar nicht.

Wenn später auf Gerät/mehr RAM die Inference-APK plötzlich grün und master/stable rot ist:
das ist der klare Fix-Hinweis — Patches aus dev/hernani-inference/* upstreamen / in master holen.
Heute: noch nicht der Fall; primärer Blocker = Emulator/RAM/ANR.

Nächste sinnvolle Schritte (später)

  1. Physisches Gerät oder Host ≥68GiB free RAM
  2. Nur eine Wallet-Package-ID installiert (kein Open-with)
  3. Survey wiederholen: stable · master · local/master-with-inference auf goa + stage
  4. Ältere F-Droid-APKs nur wenn wieder gehostet; kein Selbstbau alter Tags

Upstream branches (taler-android dev/hernani-inference/*)

Branch Role
gui-workflows macOS emulator helpers + original goa-chain-emu.sh
fix/bank-withdraw-auto-exchange Minimal GOA exchange auto-add (default build branch)
fix/withdraw-spinner-fallback Spinner + OIM; use if spinner still hangs
experimental-oim* Optional cash UI

Checklist

  • Minimal variant documented
  • Minimalvariante: was geht / was nicht (Beschränkungen)
  • Two stacks (goa / stage)
  • Dual-stack run documented (2026-07-17: both FAIL ANR, landings OK)
  • Flags design (AUTO_ANDROID / AUTO_GUI / platform defaults)
  • Headless emulator default (EMULATOR_HEADLESS=1, SwiftShader)
  • Linux default = Android suite only
  • Inference-branch policy
  • Wrapper enforces flags in every entry script (incremental)
  • Reliable unattended Confirm on low-RAM Linux emulator