4

Task:

Let connected Android tests work well on Android M.

Question:

How to enable read/write contacts permission when run connected Android test?

Problem:

I know pm command could enable the apk's permission.

adb shell pm grant <PACKAGE_NAME> <PERMISSION_NAME>

I want to run the tests which could run on both real apis and mock apis. If I fail to trigger pm command in gradle DSL, test code is not able to touch real api for security reason.

I try to add the step as first of connectedAndroidTest (connectedInstrumentTest) task. It doesn't work for the target apk has not been install yet. The command lines are called with error code.

android.testVariants.all { variant ->
    variant.connectedInstrumentTest.doFirst {
        def adb = android.getAdbExe().toString()
        exec {
            commandLine 'echo', "hello, world testVariants"
        }
        exec {
            commandLine adb, 'shell', 'pm', 'grant', variant.testedVariant.applicationId, 'android.permission.READ_ACCOUNTS'
         }
     }
 }

I try to add the step as last step of install task. It isn't called when I start connectedAndroidTest.

android.applicationVariants.all { variant ->
    if (variant.getBuildType().name == "debug") {
        variant.install.doLast {
            def adb = android.getAdbExe().toString()

            exec {
                commandLine 'echo', "hello, world applicationVariants"
            }
            exec {
                commandLine adb, 'shell', 'pm', 'grant', variant.applicationId, 'android.permission.READ_ACCOUNTS'
            }
        }
    }
}

My plan is to enable permissions before tests are launched. I don't know which task is proper one. It looks like connectedVariantAndroidTest doesn't depend on installVariant, though they both call adb install.

I try to run the pm grant from test cases. It fails as expected.

I will accept other solutions to run the android tests well.

KPrince36
  • 2,886
  • 2
  • 21
  • 29
Stony Wang
  • 53
  • 1
  • 6
  • 1
    I think this article and the comments can help you http://product.reverb.com/2015/06/06/disabling-animations-in-espresso-for-android-testing/ – albodelu Nov 19 '15 at 22:50

1 Answers1

9

I think that you need to create your own task depending on installDebug and then make connectedDebugAndroidTest depend on your task.

People does it to disable animations and works, you force the app installation and grant your specific permission before the android tests are executed like this:

def adb = android.getAdbExe().toString()

task nameofyourtask(type: Exec, dependsOn: 'installDebug') { // or install{productFlavour}{buildType}
    group = 'nameofyourtaskgroup'
    description = 'Describe your task here.'
    def mypermission = 'android.permission.READ_ACCOUNTS'
    commandLine "$adb shell pm grant ${variant.applicationId} $mypermission".split(' ')
}

tasks.whenTaskAdded { task ->
    if (task.name.startsWith('connectedDebugAndroidTest')) { // or connected{productFlavour}{buildType}AndroidTest
        task.dependsOn nameofyourtask
    }
}

You can add this code to a new yourtask.gradle file and add the next line at the bottom of the build.gradle file:

apply from: "yourtask.gradle"

And declare your permission in the proper manifest

<uses-permission android:name="android.permission.READ_ACCOUNTS" />

Update:

Fixed commandLine command like you did on your version for multiple variants, thanks.

android.applicationVariants.all { variant ->
    if (variant.getBuildType().name == "debug") {
        task "configDevice${variant.name.capitalize()}" (type: Exec){
            dependsOn variant.install

            group = 'nameofyourtaskgroup'
            description = 'Describe your task here.'

            def adb = android.getAdbExe().toString()
            def mypermission = 'android.permission.READ_ACCOUNTS'
            commandLine "$adb shell pm grant ${variant.applicationId} $mypermission".split(' ')
        }
        variant.testVariant.connectedInstrumentTest.dependsOn "configDevice${variant.name.capitalize()}"
    }
}
albodelu
  • 7,931
  • 7
  • 41
  • 84
  • 1
    Thank Ardock. [Here is my modified version for multiple variants.](https://gist.github.com/stonyw/339f16ae8a79660825eb) – Stony Wang Nov 23 '15 at 16:57
  • Sorry for a noob question, build could you point to a guide or paste your code of how to create a gradle task? – Vedant Agarwala Dec 30 '15 at 16:18
  • I don't see when install{flavour}Debug task is ran. It's not shown as a task in the Gradle console when I run the tests, although clearly the apks get installed at some point. – Radu Jan 18 '17 at 17:17
  • for me this gives something looking like a permission problem … is the task allowed to perform such actions per default, or possible the operating system prohibiting this? like: * What went wrong: Execution failed for task ':Remote:grantAllDebugPermissions'. > A problem occurred starting process 'command 'java.lang.UNIXProcess@6081a6a2'' any ideas? – cV2 Feb 10 '17 at 15:34
  • 1
    some times it can be helpful to iterate directly on `testVariants` instead of `applicationVariants` – JE42 Dec 19 '19 at 07:18