单元测试与Espresso测试资源统一存储及File对象读取咨询
当然可以统一存储这些测试资源!下面给你两种实用的方案,帮你搞定单元测试和Espresso测试的资源共享,同时满足以File对象读取的需求:
方案一:将资源放在src/main/assets目录(推荐给需要在主代码和测试中共用的资源)
这个目录的资源会被打包进APK,所以Espresso(instrumented测试)可以直接读取;而本地单元测试(JVM测试)需要稍作配置来访问它。
1. 配置Gradle让单元测试能访问main/assets
在你的模块级build.gradle(或build.gradle.kts)中添加以下配置:
// Groovy版本 sourceSets { test.resources.srcDirs += files('src/main/assets') } // Kotlin DSL版本 sourceSets { test { resources.srcDirs += file("src/main/assets") } }
这样单元测试就能把main/assets目录当成自己的资源目录来访问了。
2. 读取成File对象的方式
Espresso测试(instrumented测试):
你可以先把assets里的文件复制到设备的可读写目录,再获取File对象——因为直接从assets获取File是不行的(assets里的文件是APK的一部分,不是真实的文件系统路径):fun getAssetAsFile(context: Context, assetName: String): File { val tempFile = File(context.cacheDir, assetName) context.assets.open(assetName).use { inputStream -> tempFile.outputStream().use { outputStream -> inputStream.copyTo(outputStream) } } return tempFile } // 使用示例 val sampleFile = getAssetAsFile(InstrumentationRegistry.getInstrumentation().targetContext, "sample.txt")本地单元测试:
因为我们已经配置了Gradle,单元测试可以直接通过类加载器获取资源的绝对路径,从而生成File对象:val resourceUrl = javaClass.classLoader?.getResource("sample.txt") val sampleFile = resourceUrl?.let { File(it.path) }
方案二:创建共享测试资源目录(仅用于测试的资源)
如果你的资源只在测试中用到,不想打包进主APK,可以创建一个共享的测试资源目录,让单元测试和Espresso测试都能访问它。
1. 创建共享目录并配置Gradle
- 首先在模块根目录创建
src/sharedTest/resources目录,把sample.txt放在这里。 - 然后在模块级
build.gradle中添加配置:
// Groovy版本 sourceSets { test.resources.srcDirs += files('src/sharedTest/resources') androidTest.resources.srcDirs += files('src/sharedTest/resources') } // Kotlin DSL版本 sourceSets { test { resources.srcDirs += file("src/sharedTest/resources") } androidTest { resources.srcDirs += file("src/sharedTest/resources") } }
2. 读取成File对象的方式
本地单元测试:和方案一的单元测试读取方式一样,直接通过类加载器获取:
val resourceUrl = javaClass.classLoader?.getResource("sample.txt") val sampleFile = resourceUrl?.let { File(it.path) }Espresso测试:同样需要把资源复制到设备的可读写目录,因为instrumented测试无法直接访问电脑上的共享目录文件。你可以先通过Gradle自动把共享资源复制到androidTest的assets目录,再用方案一的Espresso读取方式:
先在Gradle中添加复制任务:// Groovy版本 task copySharedTestResourcesToAndroidTestAssets(type: Copy) { from 'src/sharedTest/resources' into 'src/androidTest/assets' } preBuild.dependsOn copySharedTestResourcesToAndroidTestAssets // Kotlin DSL版本 val copySharedTestResourcesToAndroidTestAssets by tasks.registering(Copy::class) { from("src/sharedTest/resources") into("src/androidTest/assets") } tasks.preBuild.configure { dependsOn(copySharedTestResourcesToAndroidTestAssets) }之后就可以用方案一中的
getAssetAsFile方法来获取File对象了。
注意:如果选择方案二,每次修改共享资源后,Gradle会自动同步到androidTest的assets目录,不用手动复制。
内容的提问来源于stack exchange,提问作者jakub

