You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Instrumentation(Espresso)测试前将测试数据文件上传至设备?

刚好我之前也遇到过类似的Instrumental测试文件部署问题,给你几个实用的解决方案,完美适配你的场景:

方案1:利用被测APK的私有目录(无需额外权限)

这是最推荐的方案,完全绕开外部存储权限问题——因为应用对自己的私有目录拥有完全读写权限,不需要申请任何外部存储相关权限。

步骤如下:

  • 把你的测试数据文件放到测试模块的 src/androidTest/assets 文件夹下(如果没有就新建一个)
  • 在测试代码中,通过 Instrumentation.getTargetContext() 获取被测应用的上下文,这样就能直接操作它的私有文件目录
  • 用AssetManager把测试文件从测试APK的assets复制到被测APK的私有目录里

代码示例(Kotlin):

import androidx.test.platform.app.InstrumentationRegistry
import java.io.File
import java.io.FileOutputStream

@Test
fun prepareTestFile() {
    val instrumentation = InstrumentationRegistry.getInstrumentation()
    // 获取被测应用的上下文,用于访问它的私有目录
    val targetAppContext = instrumentation.targetContext
    // 获取测试APK的AssetManager,读取测试文件
    val testAssetManager = instrumentation.context.assets

    // 要复制的测试文件名
    val testFileName = "sample_data.pdf"
    // 目标路径:被测APK的私有文件目录
    val targetFile = File(targetAppContext.filesDir, testFileName)

    // 执行复制操作
    testAssetManager.open(testFileName).use { inputStream ->
        FileOutputStream(targetFile).use { outputStream ->
            inputStream.copyTo(outputStream)
        }
    }

    // 现在被测应用可以直接读取这个文件,无需任何权限
    // 接下来调用被测应用的文件选择/处理逻辑即可
}
方案2:用adb命令手动/脚本推送文件

如果需要在测试前预先部署文件,或者测试场景需要文件在外部存储(比如用户手动选择的场景),可以用adb命令推送:

推送到外部公共目录(比如Download)

adb push your_test_file.txt /sdcard/Download/

注意:Android 10+ 访问公共目录需要 MANAGE_EXTERNAL_STORAGE 权限,但如果你的测试场景是模拟用户通过**存储访问框架(SAF)**选择文件,那么不需要权限——因为SAF是用户授权的,被测应用可以正常读取用户选择的文件。

推送到被测APK的私有目录(无需root,仅适用于debug包)

如果不想用外部存储,又想直接把文件放到被测APK的私有目录,可以用run-as命令:

# 先把文件推送到临时目录
adb push your_test_file.txt /sdcard/
# 切换到被测应用的身份,把文件复制到它的私有文件目录
adb shell run-as com.your.target.app.package cp /sdcard/your_test_file.txt files/

把com.your.target.app.package替换成你被测应用的包名即可。

方案3:封装Test Rule自动化文件部署

如果多个测试用例都需要部署相同的测试文件,可以封装一个Test Rule,让它在每个测试用例执行前自动完成文件复制,减少重复代码:

import androidx.test.platform.app.InstrumentationRegistry
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.io.File
import java.io.FileOutputStream

class DeployTestFileRule(private val testFileName: String) : TestRule {
    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            override fun evaluate() {
                // 执行文件复制逻辑
                val instrumentation = InstrumentationRegistry.getInstrumentation()
                val targetAppContext = instrumentation.targetContext
                val testAssetManager = instrumentation.context.assets

                val targetFile = File(targetAppContext.filesDir, testFileName)
                testAssetManager.open(testFileName).use { input ->
                    FileOutputStream(targetFile).use { output ->
                        input.copyTo(output)
                    }
                }

                // 执行原测试用例
                base.evaluate()
            }
        }
    }
}

然后在测试类中直接使用这个Rule:

import org.junit.Rule
import org.junit.Test

class FileProcessingTest {
    @get:Rule
    val deployTestFileRule = DeployTestFileRule("sample_data.pdf")

    @Test
    fun testFileProcessingFlow() {
        // 此时测试文件已经自动部署到被测APK的私有目录
        // 直接调用被测应用的文件处理逻辑即可
        val fileProcessor = FileProcessor()
        val result = fileProcessor.processFile("sample_data.pdf")
        // 断言处理结果符合预期
        assert(result.isSuccess)
    }
}

补充:为什么你之前的方案失败?

你之前尝试从测试APK的assets写入外部存储失败,是因为测试APK和被测APK的权限是相互独立的——即使测试APK申请了WRITE_EXTERNAL_STORAGE权限,被测APK没有这个权限的话,依然无法写入外部存储。而上面的方案1直接利用被测APK的私有目录,完全不需要外部存储权限,刚好解决这个问题。

内容的提问来源于stack exchange,提问作者engilyin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:19:22