我找到了以下方法:
创建一些负责初始化并且必须首先运行的测试类。要按特定顺序运行测试,我使用的是这样的 Suite 类:
@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
虽然还有很多与这个问题无关的其他问题。例如。要运行测试,您必须保留一些可以在发布版本中删除的类和方法,以及 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);
}
}
}
较旧的设备只是忽略 GrantPermissionRule,因此应用清单中的权限就足够了。
还有其他想法,例如更改 gradle 脚本等。但我最终得到了上面的解决方案。