Move from SNAPSHOT to alpha / rc

Change-Id: I75c04745b3641ad4cabd5df1e3c8b4518e9db9a6
bw/uiautomator3
Ben Weiss 2 months ago
parent dea3da5fa7
commit e986cd2a78
No known key found for this signature in database
GPG Key ID: 8424F9C1E763A74C

@ -69,6 +69,7 @@ baselineProfile {
dependencies {
implementation(libs.androidx.benchmark.macro)
implementation(libs.androidx.benchmark.traceprocessor)
implementation(libs.androidx.test.core)
implementation(libs.androidx.test.espresso.core)
implementation(libs.androidx.test.ext)

@ -18,7 +18,7 @@ package com.google.samples.apps.nowinandroid
import android.view.accessibility.AccessibilityNodeInfo
import androidx.test.uiautomator.UiAutomatorTestScope
import androidx.test.uiautomator.onView
import androidx.test.uiautomator.onElement
import androidx.test.uiautomator.textAsString
import androidx.test.uiautomator.watcher.PermissionDialog
@ -34,12 +34,12 @@ fun UiAutomatorTestScope.startAppAndAllowPermission() {
}
fun UiAutomatorTestScope.textVisibleOnTopAppBar(text: String) =
onTopAppBar { textAsString == text && isVisibleToUser }
onTopAppBar { textAsString() == text && isVisibleToUser }
fun UiAutomatorTestScope.onTopAppBar(
timeoutMs: Long = 10000,
pollIntervalMs: Long = 100,
block: AccessibilityNodeInfo.() -> (Boolean),
) {
onView { viewIdResourceName == "niaTopAppBar" }.onView(timeoutMs, pollIntervalMs, block)
onElement { viewIdResourceName == "niaTopAppBar" }.onElement(timeoutMs, pollIntervalMs, block)
}

@ -21,6 +21,6 @@ import androidx.test.uiautomator.textAsString
import com.google.samples.apps.nowinandroid.textVisibleOnTopAppBar
fun UiAutomatorTestScope.goToBookmarksScreen() {
onView { textAsString == "Saved" }.click()
onElement { textAsString == "Saved" }.click()
textVisibleOnTopAppBar("Saved")
}

@ -23,11 +23,11 @@ import com.google.samples.apps.nowinandroid.textVisibleOnTopAppBar
import org.junit.Assert.fail
fun UiAutomatorTestScope.forYouWaitForContent() {
onViewOrNull(timeoutMs = 500) { viewIdResourceName == "loadingWheel" && !isVisibleToUser }
onElementOrNull(timeoutMs = 500) { viewIdResourceName == "loadingWheel" && !isVisibleToUser }
// Sometimes, the loading wheel is gone, but the content is not loaded yet
// So we'll wait here for topics to be sure
// Timeout here is quite big, because sometimes data loading takes a long time!
onView(timeoutMs = 30_000) {
onElement(timeoutMs = 30_000) {
viewIdResourceName == "forYou:topicSelection" && childCount > 0 && isVisibleToUser
}
}
@ -37,7 +37,7 @@ fun UiAutomatorTestScope.forYouWaitForContent() {
* [recheckTopicsIfChecked] Topics may be already checked from the previous iteration.
*/
fun UiAutomatorTestScope.forYouSelectTopics(recheckTopicsIfChecked: Boolean = false) {
onView { viewIdResourceName == "forYou:topicSelection" }.run {
onElement { viewIdResourceName == "forYou:topicSelection" }.run {
if (children.isEmpty()) {
fail("No topics found, can't generate profile for ForYou page.")
}
@ -59,14 +59,14 @@ fun UiAutomatorTestScope.forYouSelectTopics(recheckTopicsIfChecked: Boolean = fa
}
fun UiAutomatorTestScope.forYouScrollFeedDownUp() {
onView { viewIdResourceName == "forYou:feed" }.run {
onElement { viewIdResourceName == "forYou:feed" }.run {
fling(Direction.DOWN)
fling(Direction.UP)
}
}
fun UiAutomatorTestScope.setAppTheme(isDark: Boolean) {
onView { textAsString == if (isDark) "Dark" else "Light" }.click()
onView { textAsString == "OK" }.click()
onElement { textAsString() == if (isDark) "Dark" else "Light" }.click()
onElement { textAsString() == "OK" }.click()
textVisibleOnTopAppBar("Now in Android")
}

@ -22,21 +22,21 @@ import androidx.test.uiautomator.textAsString
import com.google.samples.apps.nowinandroid.textVisibleOnTopAppBar
fun UiAutomatorTestScope.goToInterestsScreen() {
onView { textAsString == "Interests" }.click()
onElement { textAsString() == "Interests" }.click()
textVisibleOnTopAppBar("Interests")
// Wait until content is loaded by checking if interests are loaded
assert(onViewOrNull { viewIdResourceName == "loadingWheel" && !isVisibleToUser } == null)
assert(onElementOrNull { viewIdResourceName == "loadingWheel" && !isVisibleToUser } == null)
}
fun UiAutomatorTestScope.interestsScrollTopicsDownUp() {
onView { viewIdResourceName == "interests:topics" }.run {
onElement { viewIdResourceName == "interests:topics" }.run {
// Set some margin from the sides to prevent triggering system navigation
setGestureMargin(uiDevice.displayWidth / 5)
setGestureMargin(device.displayWidth / 5)
fling(Direction.DOWN)
fling(Direction.UP)
}
}
fun UiAutomatorTestScope.interestsWaitForTopics() {
onView(30_000) { textAsString == "Accessibility" }
onElement(30_000) { textAsString() == "Accessibility" }
}

@ -16,10 +16,14 @@
package com.google.samples.apps.nowinandroid.interests
import androidx.benchmark.ExperimentalBenchmarkConfigApi
import androidx.benchmark.ExperimentalConfig
import androidx.benchmark.StartupInsightsConfig
import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.FrameTimingMetric
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.textAsString
import androidx.test.uiautomator.uiAutomator
@ -30,6 +34,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@OptIn(ExperimentalBenchmarkConfigApi::class, ExperimentalPerfettoCaptureApi::class)
@RunWith(AndroidJUnit4::class)
class ScrollTopicListBenchmark {
@get:Rule
@ -46,13 +51,14 @@ class ScrollTopicListBenchmark {
compilationMode = compilationMode,
iterations = ITERATIONS,
startupMode = StartupMode.WARM,
experimentalConfig = ExperimentalConfig(startupInsightsConfig = StartupInsightsConfig(true)),
setupBlock = {
uiAutomator {
// Start the app
pressHome()
startAppAndAllowPermission()
// Navigate to interests screen
onView { textAsString == "Interests" }.click()
onElement { textAsString() == "Interests" }.click()
}
},
) {

@ -68,7 +68,7 @@ class ScrollTopicListPowerMetricsBenchmark {
uiAutomator {
pressHome()
startAppAndAllowPermission()
onView { contentDescription == "Settings" }.click()
onElement { contentDescription == "Settings" }.click()
setAppTheme(isDark)
}
},

@ -21,7 +21,7 @@ import androidx.benchmark.macro.FrameTimingMetric
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.onView
import androidx.test.uiautomator.onElement
import androidx.test.uiautomator.textAsString
import androidx.test.uiautomator.uiAutomator
import com.google.samples.apps.nowinandroid.ITERATIONS
@ -53,7 +53,7 @@ class TopicsScreenRecompositionBenchmark {
pressHome()
startAppAndAllowPermission()
// Navigate to interests screen
onView { textAsString == "Interests" }.click()
onElement { textAsString() == "Interests" }.click()
}
},
) {
@ -61,7 +61,7 @@ class TopicsScreenRecompositionBenchmark {
interestsWaitForTopics()
repeat(3) {
// Toggle bookmarked
onView { viewIdResourceName == "interests:topics" }.onView { isCheckable }
onElement { viewIdResourceName == "interests:topics" }.onElement { isCheckable }
.click()
}
}

@ -0,0 +1,84 @@
/*
* Copyright 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.userjourney
import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.scrollToElement
import androidx.test.uiautomator.textAsString
import androidx.test.uiautomator.uiAutomator
import androidx.test.uiautomator.waitForStable
import androidx.test.uiautomator.watcher.PermissionDialog
import com.google.samples.apps.nowinandroid.BaselineProfileMetrics
import com.google.samples.apps.nowinandroid.ITERATIONS
import com.google.samples.apps.nowinandroid.PACKAGE_NAME
import com.google.samples.apps.nowinandroid.foryou.forYouSelectTopics
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class NewUserJourneyBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun measureJourney() = benchmarkRule.measureRepeated(
packageName = PACKAGE_NAME,
metrics = BaselineProfileMetrics.allMetrics,
compilationMode = CompilationMode.DEFAULT,
startupMode = StartupMode.COLD,
iterations = ITERATIONS,
) {
uiAutomator {
startApp(PACKAGE_NAME)
watchFor(PermissionDialog) {
clickAllow()
}
// Select some topics
forYouSelectTopics()
onElement { textAsString() == "Done" }.click()
onElement { isScrollable }.scroll(Direction.DOWN, 0.25f)
onElement { textAsString() == "Interests" }.click()
activeWindowRoot().waitForStable()
onElement { isScrollable }.scrollToElement(
direction = Direction.DOWN,
block = {
textAsString() == "Performance"
},
).click()
// Enable dynamic color in settings
onElement { contentDescription == "Settings" }.click()
onElement { textAsString() == "Yes" }.click()
pressBack()
// Search for "AndroidX releases"
onElement { contentDescription == "Search" }.click()
// Wait for animations to finish
activeWindowRoot().waitForStable()
type("AndroidX releases")
pressEnter()
}
}
}

@ -18,7 +18,7 @@ androidxEspresso = "3.6.1"
androidxHiltNavigationCompose = "1.2.0"
androidxLifecycle = "2.8.7"
androidxLintGradle = "1.0.0-alpha03"
androidxMacroBenchmark = "1.4.0-alpha11"
androidxMacroBenchmark = "1.4.0-rc01"
androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.8.5"
androidxProfileinstaller = "1.4.1"
@ -27,7 +27,7 @@ androidxTestExt = "1.2.1"
androidxTestRules = "1.6.1"
androidxTestRunner = "1.6.2"
androidxTracing = "1.3.0-alpha02"
androidxUiAutomator = "2.4.0-SNAPSHOT"
androidxUiAutomator = "2.4.0-alpha05"
androidxWindowManager = "1.3.0"
androidxWork = "2.10.0"
coil = "2.7.0"
@ -69,6 +69,7 @@ android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" }
androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" }
androidx-benchmark-traceprocessor = { group = "androidx.benchmark", name = "benchmark-traceprocessor", version.ref = "androidxMacroBenchmark" }
androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom-alpha", version.ref = "androidxComposeBom" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "androidxComposeFoundation" }

Loading…
Cancel
Save