如何为Views系统制作基线配置文件

问题描述 投票:0回答:1

测试场景等待启动屏幕完成,滚动浏览 RecyclerView,然后单击其中的随机项目。您的 XML 布局包括一个 CollapsingToolbarLayout 和一个名为 mainAdsRecyclerView 的 RecyclerView,其中似乎包含广告项。

您的 UI 测试类 BaselineProfileGenerator 包含测试场景每个步骤的方法:

  1. waitSplashScreenFinish:等待toolbar_layout出现,表示启动画面完成。
  2. scrollThroughToolbarLayout:滚动 CollapsingToolbarLayout。
  3. waitForAsyncContent:等待 mainAdsRecyclerView 及其内容的出现。
  4. scrollThroughMainAdsRecyclerView:滚动浏览 RecyclerView。
  5. goToMainAdDetailJourney:点击 mainAdsRecyclerView 中的随机项目。

这个设置看起来很全面,涵盖了等待时间、滚动操作以及与 RecyclerView 的交互。但是,如果您遇到任何问题或需要进一步帮助,请随时询问!

 <com.google.android.material.appbar.CollapsingToolbarLayout
                    android:id="@+id/toolbar_layout"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:fitsSystemWindows="true"
                    app:layout_scrollFlags="scroll">

<androidx.recyclerview.widget.RecyclerView
                android:id="@+id/mainAdsRecyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipToPadding="false"
                android:paddingHorizontal="16dp"
                android:paddingBottom="120dp"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
                tools:listitem="@layout/row_ad"
                tools:visibility="gone" />
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {

    @get:Rule
    val rule = BaselineProfileRule()

    @Test
    fun generate() {
        rule.collect("com.camelan") {
            pressHome()
            startActivityAndWait()

            // Ensure the activity is fully loaded
            device.waitForIdle(10_000)

            waitSplashScreenFinish()
            scrollThroughToolbarLayout()
            waitForAsyncContent()
            scrollThroughMainAdsRecyclerView()
            goToMainAdDetailJourney()
        }
    }
}

fun MacrobenchmarkScope.waitSplashScreenFinish() {
    val timeout = 15_000L // Increase timeout to 15 seconds for more robustness
    Log.d("BaselineProfileGenerator", "Waiting for toolbar_layout to appear")
    if (!device.wait(Until.hasObject(By.res("com.camelan.main:id/toolbar_layout")), timeout)) {
        Log.e("BaselineProfileGenerator", "toolbar_layout did not appear within the timeout")
        throw IllegalStateException("toolbar_layout did not appear within the timeout")
    }
    Log.d("BaselineProfileGenerator", "toolbar_layout appeared")
}

fun MacrobenchmarkScope.scrollThroughToolbarLayout() {
    val toolbarLayout = UiScrollable(UiSelector().resourceId("com.camelan.main:id/toolbar_layout"))
    toolbarLayout.flingToEnd(10)
    device.waitForIdle()
}

fun MacrobenchmarkScope.waitForAsyncContent() {
    val timeout = 15_000L // Increase timeout to 15 seconds for more robustness
    Log.d("BaselineProfileGenerator", "Waiting for mainAdsRecyclerView to appear")
    if (device.wait(Until.hasObject(By.res("com.camelan.main:id/mainAdsRecyclerView")), timeout)) {
        val contentList = device.findObject(By.res("com.camelan.main:id/mainAdsRecyclerView"))
        if (contentList != null) {
            if (!contentList.wait(
                    Until.hasObject(By.res("com.camelan.main:id/ad_item")),
                    timeout
                )
            ) {
                Log.e("BaselineProfileGenerator", "No ad items appeared within the timeout")
                throw IllegalStateException("No ad items appeared within the timeout")
            }
        } else {
            Log.e("BaselineProfileGenerator", "mainAdsRecyclerView not found")
            throw IllegalStateException("mainAdsRecyclerView not found")
        }
    } else {
        Log.e("BaselineProfileGenerator", "mainAdsRecyclerView did not appear within the timeout")
        throw IllegalStateException("mainAdsRecyclerView did not appear within the timeout")
    }
    Log.d("BaselineProfileGenerator", "mainAdsRecyclerView appeared")
}

fun MacrobenchmarkScope.scrollThroughMainAdsRecyclerView() {
    val mainAdsRecyclerView =
        UiScrollable(UiSelector().resourceId("com.camelan.main:id/mainAdsRecyclerView"))
    mainAdsRecyclerView.flingToEnd(10)
    device.waitForIdle()
}

fun MacrobenchmarkScope.goToMainAdDetailJourney() {
    val mainAdsRecyclerView = device.findObject(By.res("com.camelan.main:id/mainAdsRecyclerView"))
    if (mainAdsRecyclerView != null) {
        val ads = mainAdsRecyclerView.findObjects(By.res("com.camelan.main:id/ad_item"))
        if (ads.isNotEmpty()) {
            val index = (iteration ?: 0) % ads.size
            ads[index].click()
            device.wait(Until.gone(By.res("com.camelan.main:id/mainAdsRecyclerView")), 5_000)
        } else {
            Log.e("BaselineProfileGenerator", "No ads found in mainAdsRecyclerView")
            throw IllegalStateException("No ads found in mainAdsRecyclerView")
        }
    } else {
        Log.e("BaselineProfileGenerator", "mainAdsRecyclerView not found")
        throw IllegalStateException("mainAdsRecyclerView not found")
    }
}
android xml kotlin baseline-profile
1个回答
0
投票

我也试过这个

    @RunWith(AndroidJUnit4::class)
class RecyclerViewActivityBaselineProfileGenerator : BaselineProfileGenerator() {

    override fun MacrobenchmarkScope.profileBlock() {
        // Start into the RecyclerViewActivity
        startActivityAndWait()
        device.waitForIdle(20_000)

        // Scrolling RecyclerView journey
        device.findObject(By.res("com.camelan.main", "mainAdsRecyclerView")).also {
            it.setGestureMargin(device.displayWidth / 10)
            it.fling(Direction.DOWN)
            it.fling(Direction.UP)
        }
    }
}

但是我收到了这个错误

    java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.test.uiautomator.UiObject2.setGestureMargin(int)' on a null object reference
at com.camelan.baselineprofile.RecyclerViewActivityBaselineProfileGenerator.profileBlock(HomeBaselineProfileGenerator.kt:20)
at com.camelan.baselineprofile.BaselineProfileGenerator$profileGenerator$1.invoke(BaselineProfileGenerator.kt:28)
at com.camelan.baselineprofile.BaselineProfileGenerator$profileGenerator$1.invoke(BaselineProfileGenerator.kt:23)
at androidx.benchmark.macro.BaselineProfilesKt$collect$1$1.invoke(BaselineProfiles.kt:77)
at androidx.benchmark.macro.BaselineProfilesKt$collect$1$1.invoke(BaselineProfiles.kt:71)
at androidx.benchmark.macro.CompilationMode$Partial.compileImpl$benchmark_macro_release(CompilationMode.kt:318)
at androidx.benchmark.macro.CompilationMode.resetAndCompile$benchmark_macro_release(CompilationMode.kt:114)
at androidx.benchmark.macro.BaselineProfilesKt.collect(BaselineProfiles.kt:71)
at androidx.benchmark.macro.junit4.BaselineProfileRule.collect(BaselineProfileRule.kt:136)
at androidx.benchmark.macro.junit4.BaselineProfileRule.collect$default(BaselineProfileRule.kt:126)
at com.camelan.baselineprofile.BaselineProfileGenerator.profileGenerator(BaselineProfileGenerator.kt:23)
© www.soinside.com 2019 - 2024. All rights reserved.