如何将测试数据文件放在设备上进行仪器测试?

How to put test data files on a device for instrumental tests?

在仪器 (Espresso) 测试之前将测试数据文件上传到设备的 best/proper 方法是什么?

我想在用户选择设备文件系统上的一些文件时测试应用功能,我的应用正在处理这些文件并准备应用状态以进行进一步的功能测试。

我试图通过第一次测试直接从测试 apk 资产将其写入文件系统。但是权限有问题。我测试过的 apk 没有 WRITE_EXTERNAL_STORAGE,而且我担心这不是一个好方法,因为现代 Android 安全模型向用户请求交互式权限。

可能我必须以某种方式将它集成到 gradle 脚本中?

另请注意,我有两种类型的测试:调试和暂存(使用 minifyEnabled 测试 apk)

我对一种也适用于 Firebase 测试实验室的方法很感兴趣。

谢谢。

我找到了以下方法来做到这一点: 创建一些负责初始化的测试 class 并且必须先 运行 。为了按特定顺序进行 运行 测试,我正在使用套件 class,如下所示:

@RunWith(Suite.class)
@Suite.SuiteClasses({TestEnvironmentInitializer.class,
        FirstTest.class,
        SecondTest.class
})
public class MyTestSuite {
}

它可能是 运行 来自 cmd 的:

 ./gradlew yourappmodule:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=your.package.androidtest.MyTestSuite 

或者,如果您想测试即将发布的 apk(使用 minifyEnabled 等剥离)并使用 testBuildType "staging",您可以称它为:

./gradlew yourappmodule:connectedStagingAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=your.package.androidtest.MyTestSuite 

尽管还有一堆其他问题与这个问题无关。例如。 运行 测试你必须保留一些你可以在发布版本中删除的 classes 和方法,加上 apk 标志等。

当然,您可以直接从 Android Studio

中像往常一样调用它

关键问题是权限。所以你只需要在你的 TestEnvironmentInitializer

中使用这行代码
@Rule
public GrantPermissionRule runtimePermissionRule = GrantPermissionRule.grant(
        Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE);

当然还要将此权限添加到应用程序中 AndroidManifest.xml

我的问题是最初测试的应用程序不应该有 WRITE_EXTERNAL_STORAGE 权限。

而且我没有找到解决这个问题的好方法。我试图仅为我的测试 apk 添加此权限。从逻辑上讲,因为我的 TestEnvironmentInitializer 在测试 apk 中,我希望 WRITE 权限应该在测试 apk 中设置。将具有此权限的测试 apk AndroidManifest.xml 片段放在 src/androidTest 下可以很容易地实现 但这没有帮助。因为这个权限应该是在原来测试的apk里面设置的。

所以我同意一些妥协。并在 src/ 文件夹下添加 debug 和 staging 文件夹,并将具有 WRITE 权限的 AndroidManifest.xml 片段放在那里。 因此,当我 运行 进行我的测试时,它们是 运行 作为调试或暂存并且存在权限。但是它不会出现在真正的版本中。

我的测试数据文件我已经添加到src/androidTest

下的assets文件夹中

这是我的初始化程序测试的示例:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class TestEnvironmentInitializer {

    @Rule
    public GrantPermissionRule runtimePermissionRule = GrantPermissionRule.grant(
            Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE);


    @Test
    public void initEnvironment() {
        try {

            Context testContext = InstrumentationRegistry.getInstrumentation().getContext();


            File root = Environment.getExternalStorageDirectory();


            File testDataFolder = new File(root, "testData");

            if(testDataFolder.mkdirs()) {

                File destFile = new File(testDataFolder, "test_data.dat");
                if (!destFile.exists()) {
                    copyAssetToExternalStorage(testContext, "assetssubfolder/test_data.dat", destFile);
                }
            }

        } catch (Throwable e) {
            System.exit(-1);
        }
    }

    void copyAssetToExternalStorage(Context context, String fileToCopy, File dest) throws
            IOException {

        try (InputStream src = context.getAssets().open(fileToCopy)) {

            try (FileOutputStream destStream = new FileOutputStream(
                    dest)) {

                copyStream(src, destStream);
            }
        }
    }

    void copyStream(InputStream src, OutputStream dest) throws IOException {

        byte[] buffer = new byte[1024];
        int read;
        while ((read = src.read(buffer)) != -1) {
            dest.write(buffer, 0, read);
        }
    }
}

较旧的设备会简单地忽略 G运行tPermissionRule,因此应用程序清单中的权限就足够了。

还有另一个想法,比如更改 gradle 脚本等。但我最终得到了上面的解决方案。