From 99a40a09e76a9732859e36a21f00992c7b259751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Tue, 3 Nov 2026 12:17:51 +0100 Subject: [PATCH] test: log uncaught exceptions in the demo smoke tests The smoke tests replace the default uncaught exception handler with one that only records the exception. If the main thread throws, the app hangs instead of crashing and the test may never reach assertNoUncaughtExceptions(), so the exception was lost. Log it under the DemoSmokeTest tag as well. Also note in AGENTS.md to keep the screen on when running the emulator suites on a physical device: a screen timeout in the middle of a run made the demo app hang with an ANR (#1070). --- AGENTS.md | 7 +++++++ .../google/maps/android/compose/smoke/DemoAppSmokeTest.kt | 8 +++++++- .../maps/android/compose/smoke/DemoMenuNavigationTest.kt | 8 +++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a9346413..5f1900e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,6 +76,13 @@ and they are covered automatically. To run them with a device or emulator attach Add `-Pandroid.testInstrumentationRunnerArguments.requireMapLoaded=true` to also wait for map tiles to render, which needs a real key. +On a physical device, keep the screen on for the whole run (for example +`adb shell svc power stayon usb`, and `adb shell svc power stayon false` +afterwards). If the screen times out in the middle, a demo can stop resuming and +the run hangs with an ANR instead of failing (see #1070). The smoke tests also +log any uncaught exception under the `DemoSmokeTest` tag, so check logcat if a +run hangs. + Running `maps-app` requires a Maps API key: put `MAPS_API_KEY=...` in `secrets.properties` at the repo root (see `local.defaults.properties` for the template). Never hardcode or commit API keys. diff --git a/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoAppSmokeTest.kt b/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoAppSmokeTest.kt index 7e01bb86..46649021 100644 --- a/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoAppSmokeTest.kt +++ b/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoAppSmokeTest.kt @@ -17,6 +17,7 @@ package com.google.maps.android.compose.smoke import android.graphics.Rect +import android.util.Log import android.view.View import android.view.ViewGroup import androidx.activity.ComponentActivity @@ -115,7 +116,10 @@ class DemoAppSmokeTest(private val demoName: String, private val demoActivity: C assumeTrue("Maps API key not specified", hasValidApiKey) defaultHandler = Thread.getDefaultUncaughtExceptionHandler() - Thread.setDefaultUncaughtExceptionHandler { _, throwable -> + Thread.setDefaultUncaughtExceptionHandler { thread, throwable -> + // Log it: if the main thread dies here the app hangs and the test may never reach + // assertNoUncaughtExceptions(), so logcat is the only place it would show up. + Log.e(TAG, "Uncaught exception on thread ${thread.name}", throwable) uncaughtExceptions.add(throwable) } } @@ -270,3 +274,5 @@ class DemoAppSmokeTest(private val demoName: String, private val demoActivity: C walk(this@mapSurfaces) } } + +private const val TAG = "DemoSmokeTest" diff --git a/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoMenuNavigationTest.kt b/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoMenuNavigationTest.kt index 165c7955..3811182a 100644 --- a/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoMenuNavigationTest.kt +++ b/maps-app/src/androidTest/java/com/google/maps/android/compose/smoke/DemoMenuNavigationTest.kt @@ -18,6 +18,7 @@ package com.google.maps.android.compose.smoke import android.app.Activity import android.os.SystemClock +import android.util.Log import android.view.View import android.view.ViewGroup import androidx.compose.ui.test.hasScrollToIndexAction @@ -77,7 +78,10 @@ class DemoMenuNavigationTest( @Before fun setUp() { defaultHandler = Thread.getDefaultUncaughtExceptionHandler() - Thread.setDefaultUncaughtExceptionHandler { _, throwable -> + Thread.setDefaultUncaughtExceptionHandler { thread, throwable -> + // Log it: if the main thread dies here the app hangs and the test may never reach + // assertNoUncaughtExceptions(), so logcat is the only place it would show up. + Log.e(TAG, "Uncaught exception on thread ${thread.name}", throwable) uncaughtExceptions.add(throwable) } } @@ -209,3 +213,5 @@ class DemoMenuNavigationTest( } } } + +private const val TAG = "DemoSmokeTest"