android – Set build failed when espresso fails-ThrowExceptions

Exception or error:

Gradle sets the build to failed when unit test failed, but set BUILD SUCCESSFUL when instrumented test fails(espresso in my case) anybody know how to force build to fail when espresso failed?

Ops: need this to integrate with Jenkins, so it must failed when unit test and espresso test failed and don’t want to use Jenkins Text-finder plugin.

How to solve:

Just to let everyone know, I founded a solution, following the answer:android-gradle-plugin 1.2.2: Flag ignoreFailures causes error in task connectedAndroidTest , I did

project.gradle.taskGraph.whenReady {
    connectedAndroidTest[flavor]Debug {
        ignoreFailures = false
    }
    connectedAndroidTest[flavor2]Debug {
        ignoreFailures = false
    }
 }

and execute ./gradlew connectedAndroidTest –continue

now it runs all instrumented test for both flavours and if there is a failure in any one of them, the build failure as well.

###

I found more clean solution, use in root build.gradle:

//if in start command "--continue" was added, then apply ignoring for android test fails
gradle.taskGraph.whenReady { graph ->
    if (gradle.startParameter.continueOnFailure) {
        graph.allTasks.findAll { it.name ==~ /connected.*AndroidTest/ }*.ignoreFailures = true
    }
}

###

This solution works for me.
Add this code to UI Test class:

// Use this TestRule to setup IdlingResource
@Rule
@JvmField
val mIdlingResourceTestRule = CustomIdlingResTestRule()

This is code of CustomIdlingResTestRule:

import androidx.test.espresso.IdlingPolicies
import androidx.test.espresso.IdlingRegistry
import com.jakewharton.espresso.OkHttp3IdlingResource
import com.kasikorn.retail.mbanking.kplus.basemodule.AppModule
import com.kasikorn.retail.mbanking.kplus.util.OkHttpProvider
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.util.concurrent.TimeUnit

/**
 * TestRule class help to setup IdlingResource
 */
class CustomIdlingResTestRule : TestRule {
    protected var mIdlingResource: CustomIdlingResource = CustomIdlingResource()

    val idlingResourceOkHttp: OkHttp3IdlingResource by lazy {
        OkHttp3IdlingResource.create(AppModule.APP_CONTEXT, OkHttpProvider.getOkHttpInstance())
    }

    override fun apply(base: Statement?, description: Description?): Statement {
        return object : Statement() {
            override fun evaluate() {
                IdlingPolicies.setMasterPolicyTimeout(60, TimeUnit.SECONDS)
                IdlingPolicies.setIdlingResourceTimeout(26, TimeUnit.SECONDS)
                IdlingRegistry.getInstance().register(idlingResourceOkHttp, mIdlingResource)
                //NOTE: use try cache to ignore UI Test Failures
                try {
                    base?.evaluate()
                } catch (e: Throwable) {
                    e.printStackTrace()
                }

                IdlingRegistry.getInstance().unregister(idlingResourceOkHttp, mIdlingResource)
            }

        }
    }
}

import android.app.Activity
import android.util.Log
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.core.internal.deps.guava.collect.Iterables
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage

class CustomIdlingResource() : IdlingResource {
    private var mIsIdle = false
    private var resourceCallback: IdlingResource.ResourceCallback? = null

    override fun getName(): String = this.javaClass.simpleName

    override fun isIdleNow(): Boolean {
        if (mIsIdle) return true
        val currentActivity = getCurrentActivity()
        Log.d("LOG", this.javaClass.simpleName + " | isIdleNow() | currentActivity: $currentActivity")
        if (currentActivity != null) {
            mIsIdle = true
            resourceCallback?.onTransitionToIdle()
        }
        return mIsIdle
    }

    override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
        this.resourceCallback = callback
    }

    private fun getCurrentActivity(): Activity? {
        val activity = arrayOfNulls<Activity>(1)
        val activities: Collection<Activity> = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED)
        activity[0] = Iterables.getOnlyElement(activities)
        return activity[0]
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *