【问题标题】:How to switch/change testInstrumentationRunner dynamically with gradle如何使用 gradle 动态切换/更改 testInstrumentationRunner
【发布时间】:2023-03-08 19:43:01
【问题描述】:

我的项目有 2 组不同的测试。一组仅使用默认 AndroidJUnitRunner 运行,另一组必须使用自定义实现 TestRunner extends MonitoringInstrumentation 运行。

目前我每次需要运行另一组测试时都通过编辑build.gradle 来切换testInstrumentationRunner

android{
      defaultConfig {
          //testInstrumentationRunner "my.custom.TestRunner"
           testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
      }
}

我知道口味可以有自己的testInstrumentationRunner,但我当前的应用程序已经有 2 个flavourDimensions。使用风味实际上是为了拥有不同版本的应用程序。我需要 2 个版本的测试应用程序,都使用不同的 testInstrumentationRunners 测试同一个应用程序。

我试图通过迭代所有测试变体来更改testInstrumentationRunner。实际上有多个testInstrumentationRunner 属性:

android.testVariants.all { TestVariant variant ->
    //readonly
    variant.variantData.variantConfiguration.instrumentationRunner

    variant.variantData.variantConfiguration.defaultConfig.testInstrumentationRunner

}

但只要调用android.testVariants,构建就会被配置,并且所有更改都不会反映在构建中。

如何动态更改 testInstrumentationRunner(来自 gradle 插件)?

我希望有 2 个不同的 gradle 任务,每个任务使用不同的 testInstrumentationRunner,但测试相同的变体。因为我打算创建一个 gradle 插件,所以解决方案也应该作为插件工作。

【问题讨论】:

    标签: android gradle android-gradle-plugin android-testing


    【解决方案1】:

    从 android gradle 插件 1.3 开始,可以创建单独的测试模块。每个测试模块都可以有自己的 testInstrumentationRunner。

    有关详细示例,请参阅 github 上的 AndroidTestingBlueprint 示例项目。

    来自@johan-stuyts 的获得赏金的解决方案工作正常(或者至少它与 android gradle 插件 1.2 一起使用)。但它使用私有 API,并且创建一个单独的模块更容易且面向未来。

    【讨论】:

    • 该示例项目没有说明单个项目中的多个测试模块,实际上它没有正确构建。
    • 示例项目不工作,没有针对不同TestRunner的配置。
    【解决方案2】:

    您是否考虑过使用控制台参数作为两种配置之间的切换?就这么简单:

    android {
          defaultConfig {
               if (project.ext.has("customRunner")) {
                   testInstrumentationRunner "my.custom.TestRunner"
               } else {
                   testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
               }
          }
    }
    

    然后例如运行gradlew aDeb -PcustomRunner,如果你想使用自定义运行器或gradlew aDeb使用默认运行。

    我知道这不是火箭科学,但越简单越好,对吧?您也可以在您的插件中使用它,只需获取 Project 对象并执行类似的操作即可。

    【讨论】:

    【解决方案3】:

    这是一个部分解决方案,但也许这会让您的事情变得不那么麻烦:它不允许您在同一个构建中使用两个测试运行器运行测试。如果你愿意,你必须克隆DeviceProviderInstrumentTestTask 的所有任务实例,在我看来,这太复杂和脆弱了。

    这对我有用(Gradle 2.4 和 Android 构建工具 1.2.3)。它使用内部 API,因此它可能不再适用于 Android 构建工具的下一个版本。

    您应该在项目评估后修改Android插件生成的任务。然后测试任务将使用这些更改。实际更改使用的测试运行器的属性是task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner。不是在配置阶段(即在任务之外)进行这些更改,而是使用任务应用更改,因此您的测试运行器仅在请求时使用。通过强制测试任务在useMyTestRunner 之后运行(如果后者是构建的一部分),测试运行器的类名将在测试任务启动时更改:

    project.afterEvaluate {
        task useMyTestRunner << {
            tasks.withType(com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.class) { task ->
                task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner = 'com.mycompany.MyTestRunner'
            }
        }
    
        tasks.withType(com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.class) { task ->
            task.mustRunAfter useMyTestRunner
        }
    }
    

    您现在可以使用为风味配置的默认测试运行器运行测试:

    gradle :myApp:connectedAndroidTest
    

    当您想使用测试运行器运行测试时,请使用:

    gradle :myApp:connectedAndroidTest :myApp:useMyTestRunner
    

    我没有为使用task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner 检索的任何属性添加对null 的检查。您应该添加它们以获得稳健性。我认为至少testedConfig 需要注意。见getInstrumentationRunner()https://android.googlesource.com/platform/tools/build/+/master/builder/src/main/java/com/android/builder/VariantConfiguration.java

    您可以在构建文件的顶部使用 com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask 的导入,因此您只需使用类的简单名称。

    【讨论】:

    • 你能帮我解决这个问题吗? stackoverflow.com/questions/67163964/…
    • @StuartDTO:我已经有一段时间没有使用 Android 和 Gradle 做了一些事情了,从那时起发生了很多变化。所以我现在无法回答这个问题。让我们希望别人会帮助你。您的问题很新,所以请耐心等待。
    【解决方案4】:

    我有一个类似的问题,我使用了 gradle 的 taskGraph。根据您的陈述“我的项目有 2 组不同的测试。”我假设您定义了不同的任务,我将它们称为 testGroupOne 和 testGroupTwo:

    task testGroupOne{
    }
    task testGroupTwo{
    }
    gradle.taskGraph.whenReady {taskGraph ->
        if(taskGraph.hasTask(testGroupOne)){
            testInstrumentationRunner "my.custom.TestRunner"
        } else if (taskGraph.hasTask(testGroupTwo)){
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
    }
    

    这使您可以在配置之后但在执行之前设置 testInstrumentationRunner 的值。

    【讨论】:

    • Android 插件已经被配置并使用配置阶段的 testInstrumentationRunner。
    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多