使用FragmentScenario进行仪器测试

Gou*_*ngh 6 android android-testing

我正在尝试使用androidx测试库的新FragmentScenario API进行本地测试和工具测试(androidTest)。该api在本地环境中运行良好,但在仪器测试中却出现错误: java.lang.AssertionError:活动永远不会变为请求状态“ [RESUMED,DESTROYED]”(上次生命周期转换=“ PRE_ON_CREATE”)

帮助我进行基础测试(androidTest)

请检查完整的错误详细信息:

java.lang.AssertionError: Activity never becomes requested state "[RESUMED, DESTROYED]" (last lifecycle transition = "PRE_ON_CREATE")
at androidx.test.core.app.ActivityScenario.waitForActivityToBecomeAnyOf(ActivityScenario.java:228)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:198)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:169)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:160)
at com.techzis.avatr.LoginFragmentTest1.dummyTest(LoginFragmentTest1.kt:26)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2152)
Run Code Online (Sandbox Code Playgroud)

仪器测试(androidTest)的代码是:

@RunWith(AndroidJUnit4::class)
class LoginFragmentTest1 {
    @Test
    fun dummyTest() {
        val scenario = launchFragmentInContainer<LoginFragment>()
        onView(ViewMatchers.withId(R.id.user_name)).perform(ViewActions.typeText("Hello World!"))
        onView(ViewMatchers.withId(R.id.user_name)).check(matches(withText("Hello World!")))
    }

}
Run Code Online (Sandbox Code Playgroud)

本地单元测试代码为:

@RunWith(AndroidJUnit4::class)
@Config(application = MyApplication::class, shadows = [ShadowAndroidXMultiDex::class])
class LoginFragmentTest2 {
    @Test
    fun dummyTest() {
        val scenario = launchFragmentInContainer<LoginFragment>()
        onView(ViewMatchers.withId(R.id.user_name)).perform(ViewActions.typeText("Hello World!"))
        onView(ViewMatchers.withId(R.id.user_name)).check(matches(withText("Hello World!")))
    }

}
Run Code Online (Sandbox Code Playgroud)

而应用程序级别的build.gradle文件是:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

apply plugin: "androidx.navigation.safeargs"

android {

    compileSdkVersion 28

    defaultConfig {
        applicationId "com.example"
        minSdkVersion 18
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
        multiDexEnabled false
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments clearPackageData: 'true'
    }

    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    dataBinding {
        enabled = true
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    androidExtensions {
        experimental = true
    }

    lintOptions {
        checkReleaseBuilds false
        // Or, if you prefer, you can continue to check for errors in release builds,
        // but continue the build even when errors are found:
        abortOnError false
    }

    kapt {
        javacOptions {
            option("-Xmaxerrs", 1000)
        }
    }

    testOptions {
        unitTests.includeAndroidResources = true
        execution 'ANDROIDX_TEST_ORCHESTRATOR'
    }


    configurations.all {
        resolutionStrategy {
            force 'com.google.code.findbugs:jsr305:3.0.2'
            force 'org.jetbrains.kotlin:kotlin-reflect:1.2.71'
        }
    }
    sourceSets {
        test { java.srcDirs += "$projectDir/src/testShared" }
        androidTest {
            java.srcDirs += "$projectDir/src/testShared"
            resources.srcDirs += "$projectDir/src/test/resources"
        }
    }
}

dependencies {
    def lifecycle_version = "2.0.0"
    def fragment_version = "1.1.0-alpha01"
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.multidex:multidex:2.0.0'
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation "androidx.fragment:fragment:$fragment_version"
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
    implementation "com.squareup.moshi:moshi-kotlin:1.8.0"
    implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    kapt 'com.github.bumptech.glide:compiler:4.8.0'
    kapt "com.android.databinding:compiler:$gradle_version"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version"
    implementation 'com.github.florent37:diagonallayout:1.1.1'

    testImplementation 'androidx.test:core:1.0.0'
    testImplementation 'org.robolectric:robolectric:4.1-alpha-1'
    androidTestImplementation 'androidx.test:runner:1.1.0'
    testImplementation 'androidx.test:runner:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.0.0'
    testImplementation 'androidx.test.ext:junit:1.0.0'
    androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
    testImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
    testImplementation 'androidx.test.espresso:espresso-core:3.1.0'
    androidTestImplementation 'androidx.test.ext:truth:1.0.0'
    testImplementation 'androidx.test.ext:truth:1.0.0'
    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
    testImplementation 'org.hamcrest:hamcrest-library:1.3'
    androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13"
    testImplementation "io.mockk:mockk:1.8.13.kotlin13"

    androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'

    androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" // Test helpers for navigation
    androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
    testImplementation "androidx.fragment:fragment-testing:$fragment_version"
    androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version" // Test helpers for LiveData
    testImplementation "androidx.arch.core:core-testing:$lifecycle_version" // Test helpers for LiveData

    androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.10.0'
    testImplementation 'com.squareup.okhttp3:mockwebserver:3.10.0'

    androidTestUtil 'androidx.test:orchestrator:1.1.0'
}
Run Code Online (Sandbox Code Playgroud)

小智 7

您需要向测试中的APK添加“片段测试”依赖性,而不是测试APK。

因此,请将您的build.gradle更新为

debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
Run Code Online (Sandbox Code Playgroud)

androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
Run Code Online (Sandbox Code Playgroud)

(这是由于FragmentScenario的实现细节所致。“ fragment-testing”声明了Activity,并由FragmentScenario使用。在测试APK中声明的活动与正在测试的APK在不同的进程中运行。为了在同一进程中执行Fragment的代码,您需要将“片段测试”库放入您的APK中,而不是置于测试APK中。)

这也是开发人员站点中的教程页面


Mar*_*Han 1

我相信 ActivityScenario 的方法存在局限性launch(Intent startActivityIntent)。它只希望 Activity 恢复或销毁,如果没有在 4.5 秒内恢复,则会抛出该错误。

public static <A extends Activity> ActivityScenario<A> launch(Intent startActivityIntent)活动场景中,检查逻辑scenario.waitForActivityToBecomeAnyOf(State.RESUMED, State.DESTROYED);

编辑此问题已修复。


归档时间:

查看次数:

2197 次

最近记录:

7 年,1 月 前