Android Marshmallow:使用Espresso测试权限?

arg*_*iwi 62 permissions android android-espresso android-6.0-marshmallow

Android Marshmallow引入的新权限方案要求在运行时检查特定权限,这意味着需要根据用户是否拒绝或允许访问来提供不同的流.

当我们使用Espresso在我们的应用程序上运行自动UI测试时,我们如何模拟或更新权限状态以测试不同的场景?

Nik*_*las 81

随着新版本的Android测试支持图书馆1.0,还有一个GrantPermissionRule,你可以在你的测试使用在开始任何测试之前授予的权限.

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);
Run Code Online (Sandbox Code Playgroud)

  • 这应该被接受为正确答案,因为它使用适当的框架并且实际上与其他解决方案进行比较. (3认同)
  • 尽管在清单中声明了权限,但我仍然遇到以下错误: 12-28 14:09:35.063 7193-7215/com.blaha.test E/GrantPermissionCallable: Permission: android.permission.SET_TIME 不能被授予! (2认同)

Roc*_*nat 38

接受的答案实际上并未测试权限对话框; 它只是绕过它.因此,如果权限对话框由于某种原因失败,则您的测试将给出错误的绿色.我鼓励实际点击"授予权限"按钮来测试整个应用行为.

看看这个解决方案:

public static void allowPermissionsIfNeeded(String permissionNeeded) {
    try { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasNeededPermission(permissionNeeded)) {
        sleep(PERMISSIONS_DIALOG_DELAY);
        UiDevice device = UiDevice.getInstance(getInstrumentation());
        UiObject allowPermissions = device.findObject(new UiSelector()
          .clickable(true) 
          .checkable(false) 
          .index(GRANT_BUTTON_INDEX));
        if (allowPermissions.exists()) {
          allowPermissions.click();
        } 
      } 
    } catch (UiObjectNotFoundException e) {
      System.out.println("There is no permissions dialog to interact with");
    } 
  } 
Run Code Online (Sandbox Code Playgroud)

在这里找到全班:https://gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

顺便说一下,由于这个答案一直很受欢迎,我们PermissionGranter在Esista和UiAutomator上面添加了Barista,以便进行绿色仪器测试:https://github.com/SchibstedSpain/Barista检查出来,因为我们会维护它按发布版本发布.


riw*_*nyk 29

当您的手机使用英语语言环境时,请尝试使用此类静态方法:

private static void allowPermissionsIfNeeded() {
    if (Build.VERSION.SDK_INT >= 23) {
        UiDevice device = UiDevice.getInstance(getInstrumentation());
        UiObject allowPermissions = device.findObject(new UiSelector().text("Allow"));
        if (allowPermissions.exists()) {
            try {
                allowPermissions.click();
            } catch (UiObjectNotFoundException e) {
                Timber.e(e, "There is no permissions dialog to interact with ");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里找到

  • 奇怪的是,这不适用于Android 6的LG Nexus 5.文本"ALLOW"未找到.使用以下工作:new UiSelector().clickable(true).checkable(false).index(1) (6认同)
  • 请注意,这不适用于非EN语言环境,或者按钮文本将来会更改.如果制造商自定义对话框,它甚至可能会失败. (3认同)

Jos*_*eca 20

您可以在运行测试之前授予权限,例如:

@Before
public void grantPhonePermission() {
    // In M+, trying to call a number will trigger a runtime dialog. Make sure
    // the permission is granted before running this test.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        getInstrumentation().getUiAutomation().executeShellCommand(
                "pm grant " + getTargetContext().getPackageName()
                        + " android.permission.CALL_PHONE");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是你无法撤销.如果您尝试pm reset-permissionspm revoke...该过程被杀死.

  • 我在谷歌测试示例代码中找到了类似的代码.它适用于该软件包中的呼叫电话示例应用程序,但如果在应用程序启动后立即询问权限(例如摄像头权限),则该应用程序无效.任何人都知道为什么? (2认同)

den*_*nys 11

实际上到目前为止,有两种方法可以做到这一点:

  1. 在测试开始之前使用adb命令授予权限(文档):

adb shell pm grant "com.your.package" android.permission.your_permission

  1. 您可以单击权限对话框并使用UIAutomator(文档)设置权限.如果您的测试是使用Espresso for Android编写的,您可以轻松地在一次测试中结合Espresso和UIAutomator步骤.


Sac*_*ghe 7

您可以在开始测试之前通过授予权限轻松实现此目的.例如,如果您在测试运行期间应该使用相机,则可以按如下方式授予权限

@Before
public void grantPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        getInstrumentation().getUiAutomation().executeShellCommand(
                "pm grant " + getTargetContext().getPackageName()
                        + " android.permission.CAMERA");
    }
}
Run Code Online (Sandbox Code Playgroud)