Android 单元测试环境配置问题 Execution failed for task ‘:mergeDebugJavaResource‘.
背景和挑战
随着人工智能(AI)技术的迅猛发展,AI在各行各业的应用前景被普遍看好。无论是在医疗、金融、教育,还是在软件开发领域,AI都展示出了巨大的潜力。然而,尽管AI能够在许多方面提供支持和提升效率,但在软件开发尤其是Android单元测试过程中,AI并不能解决所有功能问题,特别还有开发环境的问题。
ChatGPT确实能提供方案,但是在单元测试领域,尤其是Android跟UI业务强相关的测试案例上,依然是更需要人工介入的设计。
AI在Android单元测试中的制约
在Android开发过程中,单元测试是确保代码质量和功能实现的重要环节。尤其在构建复杂应用时,开发者需要对大量的类和方法进行测试。然而,面对以下两类问题,AI工具往往显得力不从心:
-
业务逻辑复杂性:
AI可能会在代码自动生成和测试用例建议方面提供帮助,但对于应用中复杂的业务逻辑,AI工具通常无法完全理解开发者的意图或业务场景。AI生成的测试用例可能覆盖面广,但由于缺乏对实际业务逻辑的深入理解,它们往往无法有效捕捉到潜在的逻辑错误和边缘情况。例如,考虑一个用户输入验证的功能,AI可能很难准确模拟用户的各种输入情境,导致某些逻辑分支未被测试到。 -
环境依赖性:
Android开发环境的配置往往复杂多变,不同的Android Studio版本、SDK版本以及第三方库的依赖关系等都会影响到单元测试的运行结果。当开发环境没有正确配置时,AI工具提供的自动化测试方案可能无法如预期运行。此外,某些调试错误的产生,往往是由于环境不一致造成的,而AI工具无法直接解决这类依赖性问题。随着Android Studio以及相关工具的更新迭代,许多开发者在配置本地环境时常常面临不兼容或设置不当的问题,这可能会导致调试错误率显著上升。
应对措施
面对AI技术在Android开发中的局限性,开发者需要采取有效的措施来确保软件质量。
-
加强人工审查:
尽管AI可以为代码和测试生成提供便利,开发者仍需在关键业务逻辑和边缘情况的测试上进行人工审查。这包括审查AI生成的测试用例,确保它们涵盖所有必要场景。 -
强化开发环境规范:
围绕Android项目建立标准化的开发环境配置文档,并鼓励团队成员严格遵循,可以有效降低因环境配置不当引发的调试错误率。同时,使用容器化技术(如Docker)可以帮助创建一致的开发环境,减少环境依赖性问题。 -
积极学习与应对AI的负面影响:
开发者应保持对AI技术动向的敏感,定期学习有关AI技术的最新研究和应用案例,合理利用AI工具的优势,同时意识到其局限性。
问题案例
环境配置
为什么编译会关联到其他app模块的报错?
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':mergeDebugJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
> 4 files found with path 'META-INF/LICENSE-notice.md' from inputs:
- E:\AndroidStudioCode\TestDemoU\.gradle\caches\transforms-4\bac8a02ec876d96f400e223a6f964115\transformed\jetified-junit-platform-engine-1.8.2.jar
- E:\AndroidStudioCode\TestDemoU\.gradle\caches\transforms-4\3ddceeb372c20321054059e75b202cf1\transformed\jetified-junit-platform-commons-1.8.2.jar
- E:\AndroidStudioCode\TestDemoU\.gradle\caches\transforms-4\1e6645cc7923ded6fc2e47df844244a4\transformed\jetified-junit-jupiter-engine-5.8.2.jar
- E:\AndroidStudioCode\TestDemoU\.gradle\caches\transforms-4\5f005f3f5e87a878afdb727ca13fce01\transformed\jetified-junit-jupiter-api-5.8.2.jar
Adding a packaging block may help, please refer to
https://developer.android.com/reference/tools/gradle-api/8.4/com/android/build/api/dsl/Packaging
for more information
问题分析:
如上错误提示显示在执行 :mergeDebugJavaResource
任务时,多个库中发现了相同的文件(在本例中是 META-INF/LICENSE-notice.md
)。这是在 Gradle 构建过程中常见的资源合并冲突问题。
mergeDebugJavaResource 解决方案
1、使用 Gradle 的 packagingOptions
:
- 可以在
build.gradle
文件中使用packagingOptions
来解决资源合并冲突。- 若不存在此项配置,请在build.gradle 新增
packagingOptions
块,用于排除重复文件。
- 若不存在此项配置,请在build.gradle 新增
- 通过配置
exclude
来排除多余的文件。例如,在android
块内添加以下代码:
Groovy (Gradle)
android {
...
packagingOptions {
exclude 'META-INF/LICENSE-notice.md' //本案例是此问题,如下是相关配置
exclude 'META-INF/LICENSE.md'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
}
Note:Gradle 是基于 Groovy 的 DSL(领域特定语言),尽管 Gradle 使用 Groovy 作为其脚本语言,但它们在用途和功能上有显著的区别。
Groovy 和 Gradle 的区别 特性 Groovy Gradle 类型 编程语言(一种基于 Java 的动态语言) 构建自动化工具 基于 Java 虚拟机 (JVM) Groovy 目的 开发各种类型的应用、脚本和测试 管理和自动化构建过程 语法 灵活、简洁,支持动态类型 基于 Groovy 的 DSL(领域特定语言) 使用领域 应用开发、快速原型、测试 项目构建、依赖管理 生态系统 与 Java 完全兼容,广泛用于各种应用 支持多种语言和框架,尤其是 Java 和 Android
2、查看冲突的依赖库:
确认冲突的文件来源于哪些库,并检查这些库的版本。如果某些库的版本过旧或不兼容,考虑升级它们。例如,可能会看到 junit-platform-engine
和 junit-platform-commons
的版本。不妨确保所有相关的 JUnit 依赖库都是相同的版本。
结果:但是如上报错的文件夹已经不存在了,还是会报错,没有采用这种方式解决,无法解除相关gradle 文件的依赖。
3、运行 Gradle 依赖报告:
使用以下命令生成依赖树,查看具体使用了哪些库及其版本:
# 查看使用的依赖库和版本
./gradlew app:dependencies
结果:可是本地环境始终有问题,是运行任何gradle都报错的版本冲突
- apiElements
- javadocElements
- runtimeElements
* What went wrong:
A problem occurred configuring root project 'Demo'.
> Could not resolve all artifacts for configuration ':classpath'.
> Could not resolve com.android.tools.build:gradle:8.4.0.
Required by:
project :
> No matching variant of com.android.tools.build:gradle:8.4.0 was found. The consumer was configured to find a library for use during runtime, compatible with Java 8, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.7' but:
- Variant 'apiElements' declares a library, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares a component for use during compile-time, compatible with Java 11 and the consumer needed a component for use during runtime, compatible with Java 8
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
- Variant 'javadocElements' declares a component for use during runtime, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its elements (required them packaged as a jar)
- Doesn't say anything about its target Java version (required compatibility with Java 8)
- Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
- Variant 'runtimeElements' declares a library for use during runtime, packaged as a jar, and its dependencies declared externally:
- Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
JDK版本不对——修改Project Structure中的JDK版本也不对。
引出更多的配置问题了,有关于单个配置,也有多文件版本适配的问题。
直接在控制台使用./gradlew命令大概是全局环境的问题,而GUI里面的单独项目gradle看起来可以运行,可是没有任何输出
4、使用 implementation
或 api
而不是 compile
:
确保在使用依赖时使用了最新的配置方法,比如 implementation
或 api
,而不是过时的 compile
。这有助于避免潜在的版本冲突。
5、清理和重建项目:
有时构建缓存可能导致问题,可以通过以下命令清理项目然后再次尝试构建项目
# 清理
./gradlew clean
# 重新构建
./gradlew assembleDebug
结果:尝试了清除和重新配置,都不可以。
测试用例设计
待完善