简体   繁体   English

Android 上的 Espresso 测试在设备上正常工作时在日志上得到错误的视图层次结构

[英]Espresso test on Android getting wrong view hierarchy on logs while working properly on device

I wrote simple example test for Activity witch tests that when i click button - new fragment opens (LoginFragment).我为 Activity 女巫测试编写了简单的示例测试,当我单击按钮时 - 新片段打开(LoginFragment)。 There is test class code:有测试 class 代码:

@RunWith(AndroidJUnit4::class)
@LargeTest
class MainActivityTest {

    @get:Rule
    var activityScenarioRule = activityScenarioRule<MainActivity>()


    @Test
    fun test_clickLogInButton_openLoginFragment() {
        onView(withId(R.id.btnEnter)).perform(click())

        onView(withId(R.id.loginFragmentLayout)).check(matches(isDisplayed()))
    }
}

This test worked correctly on one computer, but now I transferred it to another and the hierarchy of views in the log began to display incorrectly.该测试在一台计算机上正常运行,但现在我将其转移到另一台计算机上,日志中的视图层次结构开始显示不正确。 Log:日志:

androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: view.getId() is <2131362001/com.example.android:id/btnEnter>

Meanwhile, I see how the given "button press" command is actually used on the emulator and new fragment getting launched.同时,我看到了给定的“按钮按下”命令是如何在模拟器上实际使用的,并且新片段正在启动。 Thus, I assume that the test still works, but the display of the logs, and as a result, the test results, is broken.因此,我假设测试仍然有效,但是日志的显示以及测试结果被破坏了。

My dependencies.我的依赖。 I tried a lot of variants and right now i have following:我尝试了很多变体,现在我有以下内容:

    // Testing
    testImplementation 'junit:junit:4.13.2'
    testImplementation "org.json:json:20180813"
    testImplementation 'org.mockito:mockito-core:3.12.4'
    testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
    testImplementation 'org.powermock:powermock-core:2.0.9'
    testImplementation 'org.powermock:powermock-module-junit4-rule-agent:2.0.2'
    testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.2'
    testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
    testImplementation "androidx.room:room-testing:$room_version"
    //UI tests
    androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
    androidTestImplementation "androidx.test.ext:junit-ktx:1.1.3"
    debugImplementation "androidx.fragment:fragment-testing:1.4.0"
    androidTestImplementation "androidx.fragment:fragment-ktx:1.4.0"
    androidTestImplementation "androidx.test:core:1.4.0"
    androidTestImplementation "androidx.test:rules:1.4.0"
    androidTestImplementation "androidx.test:runner:1.4.0"
    androidTestImplementation "androidx.navigation:navigation-testing:2.3.5"

What i was trying to do:我想做的是:

  • Clear cache and restart清除缓存并重新启动
  • Delete apk from output folder从 output 文件夹中删除 apk
  • Test on multiple devices (real and emulators)在多个设备上测试(真实和模拟器)
  • Test on debug mode (code working properly, but logs and results of the tests are the same)在调试模式下测试(代码工作正常,但日志和测试结果相同)

On my androidTest manifest i have following:在我的 androidTest 清单上,我有以下内容:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.presentation.activities"
    android:versionCode="1"
    android:versionName="1.0">

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

</manifest>

Any suggestions how to fix it?任何建议如何解决它?

As i can see, the problem was on UI-testing itselfe.如我所见,问题出在 UI 测试本身。 I managed to fix it via adding try-catch logic to first onView action in tests.我设法通过将 try-catch 逻辑添加到测试中的第一个onView操作来修复它。 This is small fun i wrote for it:这是我为它写的小乐趣:

    private fun performActionCount(
        action: () -> Unit,
        maxRepeatTimes: Int = -1
    ) {
        var success = false
        var counter = if (maxRepeatTimes == -1) Int.MIN_VALUE else 0
        while (!success && counter < maxRepeatTimes) {
            success = try {
                counter++
                action()
                true
            } catch (e: NoMatchingViewException) {
                false
            }
        }
    }

It takes the lambda of action that you need to do and trying to execute it several times.您需要执行 lambda 操作并尝试执行多次。 Example of how i use it:我如何使用它的示例:

        performActionCount(
            action = {
                onView(withId(R.id.btnEnter)).perform(click())
            },
            maxRepeatTimes = 20
        )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM