Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage Runtime permissions android marshmallow espresso tests

I'm using espresso for testing but sometimes I try to get an image form external storage and with marshmallow I need a Runtime permission otherwise there will be an Exception crash and the test will fail.

androidTestCompile 'com.android.support.test:runner:0.4' androidTestCompile 'com.android.support.test:rules:0.4' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1' androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') {     // this library uses the newest app compat v22 but the espresso contrib still v21.     // you have to specifically exclude the older versions of the contrib library or     // there will be some conflicts     exclude group: 'com.android.support', module: 'appcompat'     exclude group: 'com.android.support', module: 'support-v4'     exclude module: 'recyclerview-v7' } androidTestCompile 'junit:junit:4.12' androidTestCompile 'com.squareup.retrofit:retrofit-mock:1.9.0' androidTestCompile 'com.squareup.assertj:assertj-android:1.1.0' androidTestCompile 'com.squareup.spoon:spoon-client:1.2.0' 

how can I manage that right?

should I write test for Runtime permissions or there's a way to disable it for testing?

should I give permissions before the tests run like she says here? https://www.youtube.com/watch?list=PLWz5rJ2EKKc-lJo_RGGXL2Psr8vVCTWjM&v=C8lUdPVSzDk

like image 651
Daniel Gomez Rico Avatar asked Sep 25 '15 17:09

Daniel Gomez Rico


People also ask

Which Android introduced the runtime permission?

From beginning with Android 6.0 Marshmallow (API LEVEL 23)( Marshmallow was released on October 5, 2015), Google has introduced a new runtime permission model. Users can then allow or deny the permission, users can also grant or revoke permission anytime from settings even if the app is already installed.

What is runtime permission?

Requesting Android Runtime Permissions The method requestPermissions(String[] permissions, int requestCode); is a public method that is used to request dangerous permissions. We can ask for multiple dangerous permissions by passing a string array of permissions.


1 Answers

UPDATE! Now you can use Rule from Android Testing Support Library

It is more proper to use than custom rules.

Outdated answer:

You can add test rule to reuse code and add more flexibility:

/**  * This rule adds selected permissions to test app  */  public class PermissionsRule implements TestRule {      private final String[] permissions;      public PermissionsRule(String[] permissions) {         this.permissions = permissions;     }      @Override     public Statement apply(final Statement base, Description description) {         return new Statement() {             @Override             public void evaluate() throws Throwable {                  allowPermissions();                  base.evaluate();                  revokePermissions();             }         };     }      private void allowPermissions() {         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {             for (String permission : permissions) {                 InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(                         "pm grant " + InstrumentationRegistry.getTargetContext().getPackageName()                                 + " " + permission);             }         }     }      private void revokePermissions() {         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {             for (String permission : permissions) {                 InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(                         "pm revoke " + InstrumentationRegistry.getTargetContext().getPackageName()                                 + " " + permission);             }         }     } } 

After that you can use this rule in your test classes:

@Rule public final PermissionsRule permissionsRule = new PermissionsRule( new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS}); 

Keep in mind:

  1. Rule does not affect on @Before methods because all rules are executed after that
  2. executeShellCommand is asynchronous and if you need accepted permissions right after test started consider adding some delay
like image 185
Denis Nek Avatar answered Sep 23 '22 12:09

Denis Nek