android - 隔离测试 APK 构建

标签 android gradle android-gradle-plugin apk android-instrumentation

我有一种情况,在带有仪器测试的 Android 项目中,我已经预编译了所有生产代码并准备作为 .apk 安装。 (一个 React Native 环境)。

每当我运行仪器测试时,我最初都会构建 AndroidTest .apk通过运行使用 Gradle:

./gradlew assembleDebugAndroidTest -DtestBuildType=debug

(即以非常标准的方式)。

麻烦的是,尽管明确指定了 xxxAndroidTest任务,所有生产代码组装 Gradle 任务也会运行。这对我来说非常浪费时间,因为——正如我所解释的,生产 apk已经存在,因此代码编译(以及打包、签名等)很少。

从本质上讲,我在生产代码中没有依赖于检测代码——甚至是 ActivityTestRule。我使用的是动态创建的,并且不直接绑定(bind)到我的主要 Activity :

Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(launchIntent, 0);
Class<?> activityClass = Class.forName(resolveInfo.activityInfo.name);
ActivityTestRule<?> activityTestRule = new ActivityTestRule(activityClass, false, false);

问题是:如何隔离/限制 Gradle 的工作,使其仅包含与测试相关的任务?我什至尝试使用 this Gradle plugin 检查任务树,但找不到一个明确的地方来“砍树”。

最佳答案

到目前为止,我已经提出了这个(启发式)解决方案,它做了两件事:

  • 我注意到大部分时间浪费是由于工作不需要的子项目。因此,该解决方案提供了一种简单的方法来排除 implementation s 来自测试大楼。
  • 在列表中剩余的任务中,插件迭代地强制禁用不相关但仍然运行的任务。

  • 它归结为这个帮助 Gradle 脚本:
    // turbo-test-apk.gradle
    
    def isEnabled = System.getProperty('TURBO_TEST_APK') != null
    
    project.ext.dependenciesExcludeTest = { depsClosure ->
        if (!isEnabled) {
            dependencies(depsClosure)
        }
    }
    
    gradle.taskGraph.whenReady { graph ->
        if (isEnabled) {
            def disabledTasks = new ArrayList<Task>(graph.allTasks.size())
    
            [/.*JsAndAssets.*/, /package.*Release/, /package.*Debug/, /compile.*/, /.*[Pp]roguard.*/, /.*[Nn]ew[Rr]elic.*/, /.*AndroidTest.*/].forEach { regex ->
                graph.allTasks.findAll { it.name ==~ regex }.forEach({ task ->
                    disabledTasks.add(task)
                    task.enabled = false
                })
            }
    
            graph.allTasks.findAll { it.name ==~ /.*AndroidTest.*/ }.forEach({ task ->
                task.enabled = true
            })
    
            println '--- Turbo test build: task scanning ---'
            disabledTasks.forEach { task ->
                if (!task.enabled) {
                    println 'Force-skipping ' + task
                }
            }
            println '---------------------------------------'
        }
    }
    

    dependenciesExcludeTest启用排除不需要的子项目,并且任务图就绪回调执行禁用。 注意正则表达式列表是定制的,不是通用的 .这对我的项目很有意义,因为 react 原生项目有一个重量级的 JS bundle 任务,称为 bundleJsAndAssets。 ,我也安装了新的遗物。然而,这可以很容易地适应任何项目。

    此外,app.gradle看起来像这样:
    apply plugin: 'com.android.application'
    
    apply from: './turbo-test-apk.gradle'
    
    dependencies {
        implementation "org.jetbrains.kotlin:$kotlin_stdlib:$kotlinVersion"
        implementation "com.android.support:support-v4:$supportLibraryVersion"
        implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
        // etc.
    }
    // These will be excluded when executing test-only mode
    dependenciesExcludeTest {
        implementation project(':@react-native-community_async-storage')
        implementation project(':any-unneeded-sub-project')
    }
    
    

    因此,当 gradle 像这样运行时(即使用自定义 TURBO_TEST_APK 属性):

    ./gradlew assembleDebugAndroidTest -DtestBuildType=debug -DTURBO_TEST_APK
    

    该脚本将应用其工作并减少整体构建时间。

    这个解决方案不是最优的:难以维护,不会省略 全部 的不必要的工作。我很高兴看到更有效的解决方案。

    关于android - 隔离测试 APK 构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56948373/

    相关文章:

    android - 无法使用 cordova-plugin-facebook4 和 phonegap-plugin-barcodescanner 构建 cordova 应用程序

    安卓工作室 3.2.1 ArtifactResolveException : Could not resolve all artifacts for configuration ':classpath'

    android - 为什么gradle构建过程会删除我的Application和Activity类?

    Android Studio 找不到我的设备 - Lenovo Yoga

    android - 如何在 Android 中创建 Panorama 360 View

    android - 使 ViewPager + WebView 连续垂直滑动

    Android按钮点击事件有时不会触发

    Gradle:如何移动任务的输出?

    android - 测试版本构建在 android 上,无需签名

    android - Gradle 构建扫描错误 : Event sink is closed