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"