How do I create test assets and grant runtime permissions in androidTest tests?
Asked Answered
W

0

9

Before you mark this as duplicate, please note that this isn't about granting permissions to the app under test, but the test apk itself.

In my app, there's functionality that takes a file from the Download dir (/sdcard/download), validates it, and copies it to the app's private store (/data/data/com.package.myapp/files/) so that the file is available when needed.

To test this functionality, I need to put a number of test files in the Download dir: Some are known valid, others are known invalid files. I've put these files in the assets dir in the androidTest group.

In my test class, I have a @BeforeClass public static void prepareAssets() method who's job is to take these files from the assets dir and copy them to the Download folder before the import & validation tests actually run.

This prepare step fails:

04-12 00:25:19.282 11231-11246/? E/TEST: Failed to prepare test assets
java.io.FileNotFoundException: /storage/emulated/0/Download/test1.jpg (Permission denied)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
    at ca.mahram.android.testextstorexfer.CopyUtil.copy(CopyUtil.java:20)
    at ca.mahram.android.testextstorexfer.ExampleInstrumentedTest.prepareAssets(ExampleInstrumentedTest.java:54)
    at java.lang.reflect.Method.invoke(Native Method)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:58)
    at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:375)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1939)

Now my app only needs the android.permission.READ_EXTERNAL_STORAGE permission to copy these files, which is what I have in the manifest.

The tests, however, need the android.permission.WRITE_EXTERNAL_STORAGE permission, which I have placed in androidTest/AndroidManifest.xml.

I've tried every trick I've come across to grant the tests the android.permission.WRITE_EXTERNAL_STORAGE to no avail.

I've (unsuccessfully) tried:

  • adb shell pm grant ca.mahram.android.testextstorexfer android.permission.WRITE_EXTERNAL_STORAGE -> Operation not allowed: java.lang.SecurityException: Package ca.mahram.android.testextstorexfer has not requested permission android.permission.WRITE_EXTERNAL_STORAGE
  • adb shell pm grant ca.mahram.android.testextstorexfer.test android.permission.WRITE_EXTERNAL_STORAGE -> Fails with FileNotFoundException (permission denied)
  • @Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); -> Fails with FileNotFoundException (permission denied)
  • InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("pm grant " + InstrumentationRegistry.getContext().getPackageName() + " " + Manifest.permission.WRITE_EXTERNAL_STORAGE); -> Fails with FileNotFoundException (permission denied)
  • InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("pm grant " + InstrumentationRegistry.getTargetContext().getPackageName() + " " + Manifest.permission.WRITE_EXTERNAL_STORAGE); -> Fails with FileNotFoundException (permission denied)

All I need is to have these assets available in the Download folder prior to the tests running. Every solution I've come across is about granting the permission to the app and I haven't found anything about granting permissions to the test apk.

I'm all out of ideas. How do I prepare these assets? Is there a better way of doing it?

Here's the sample code on Github: https://github.com/copolii/so49791104

Wexford answered 12/4, 2018 at 8:3 Comment(4)
I'm having exactly the same problem. The app under test only needs READ_EXTERNAL_STORAGE, and the test also needs WRITE_EXTERNAL_STORAGE. What is quite interesting is that when the app itself still requested (ands was granted) WRITE_EXTERNAL_STORAGE, that was also usable by the test ...Mitchel
@JensMüller Yeah, that's why I tried adding a manifest for the test with the permission changed to WRITE_EXTERNAL_STORAGE, but I don't think androidTest/Androidmanifest.xml gets used in the same way as others, e.g. debug/AndroidManifest.xmlWexford
You can run InstrumentationRegistry.getContext().getAssets().open("PATHTOFILE") to read from the assets directoryTenuous
were you ever able to figure out a solution? Running into a similar problem myself currently.Evanescent

© 2022 - 2024 — McMap. All rights reserved.