【问题标题】:Set build failed when espresso fails浓缩咖啡失败时设置构建失败
【发布时间】:2024-01-08 08:01:01
【问题描述】:

Gradle 在单元测试失败时将构建设置为失败,但在仪器测试失败时设置 BUILD SUCCESSFUL(在我的情况下为 espresso)有人知道如何在 espresso 失败时强制构建失败吗?

Ops:需要这个与 Jenkins 集成,所以当单元测试和 espresso 测试失败并且不想使用 Jenkins Text-finder 插件时它必须失败。

【问题讨论】:

    标签: android jenkins gradle automated-tests android-espresso


    【解决方案1】:

    只是为了让大家知道,我创建了一个解决方案,按照答案:android-gradle-plugin 1.2.2: Flag ignoreFailures causes error in task connectedAndroidTest,我做到了

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

    并执行 ./gradlew connectedAndroidTest --continue

    现在它运行两种风格的所有仪器测试,如果其中任何一种出现故障,构建也会失败。

    【讨论】:

      【解决方案2】:

      我找到了更干净的解决方案,在 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
          }
      }
      

      【讨论】:

        【解决方案3】:

        这个解决方案对我有用。 将此代码添加到 UI 测试类:

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

        这是 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]
            }
        }
        

        【讨论】: