it-roy-ru.com

Android Marshmallow: проверка разрешений с помощью эспрессо?

Новая схема разрешений, представленная Android Marshmallow, требует проверки определенных разрешений во время выполнения, что подразумевает необходимость предоставления различных потоков в зависимости от того, запрещает ли пользователь доступ или разрешает его.

Поскольку мы используем Espresso для запуска автоматических тестов пользовательского интерфейса в нашем приложении, как мы можем смоделировать или обновить состояние разрешений для тестирования различных сценариев?

53
argenkiwi

С новым выпуском библиотеки поддержки тестирования Android 1.0 , есть GrantPermissionRule , который вы можете использовать в своих тестах для предоставления разрешения перед началом любых тестов.

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION);
63
Niklas

Принятый ответ на самом деле не проверяет диалог разрешений; это просто обходит это. Таким образом, если по какой-либо причине диалоговое окно разрешений завершится неудачно, ваш тест выдаст ложный зеленый цвет. Я рекомендую нажать кнопку «дать разрешения», чтобы проверить поведение всего приложения.

Посмотрите на это решение:

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");
    } 
  } 

Найти весь класс здесь: https://Gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

Кстати, поскольку этот ответ был популярным, мы добавили PermissionGranter к Barista, нашему инструменту над Espresso и UiAutomator, чтобы сделать инструментальные тесты зелеными: https://github.com/SchibstedSpain/Barista проверить это, потому что мы будем поддерживать его релиз за выпуском.

33
Roc Boronat

Попробуйте использовать такой статический метод, когда ваш телефон работает на английском языке:

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 ");
            }
        }
    }
}

Я нашел это здесь

29
riwnodennyk

Вы можете предоставить разрешения до запуска теста, например:

@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");
    }
}

Но вы не можете отозвать. Если вы попробуете pm reset-permissions или pm revoke..., процесс будет остановлен.

19
Jose Alcérreca

На самом деле, я знаю 2 способа сделать это:

  1. Предоставьте разрешение с помощью команды adb перед началом теста ( документация ):

adb Shell pm grant "com.your.package" Android.permission.your_permission

  1. Вы можете нажать на диалоговое окно разрешений и установить разрешение с помощью UIAutomator ( документация ). Если ваши тесты написаны с помощью Espresso для Android, вы можете легко объединить шаги Espresso и UIAutomator в одном тесте.
11
denys

Вы можете легко добиться этого, предоставив разрешение перед началом теста. Например, если вы должны использовать камеру во время тестового прогона, вы можете предоставить разрешение следующим образом

@Before
public void grantPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        getInstrumentation().getUiAutomation().executeShellCommand(
                "pm grant " + getTargetContext().getPackageName()
                        + " Android.permission.CAMERA");
    }
}
7
Sachini Samarasinghe

ESPRESSO ОБНОВЛЕНИЕ

Эта единственная строка кода предоставляет все разрешения, перечисленные в качестве параметра в методе грантов с немедленным эффектом. Другими словами, приложение будет рассматриваться как если бы разрешения уже были предоставлены - не более диалоги

@Rule @JvmField
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION)

и Gradle

dependencies {
  ...
  testImplementation "junit:junit:4.12"
  androidTestImplementation "com.Android.support.test:runner:1.0.0"
  androidTestImplementation "com.Android.support.test.espresso:espresso-core:3.0.0"
  ...
}

ссылка: https://www.kotlindevelopment.com/runtime-permissions-espresso-done-right/

3
murt

Спасибо @niklas за решение. В случае, если кто-то хочет предоставить несколько разрешений в Java:

 @Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.CAMERA);
0
learner

Я знаю, что ответ принят, однако вместо предложения if, которое предлагалось снова и снова, другим более элегантным подходом было бы сделать следующее в реальном тесте, который вы хотите для конкретной версии ОС:

@Test
fun yourTestFunction() {
    Assume.assumeTrue(Build.VERSION.SDK_INT >= 23)
    // the remaining assertions...
}

Если функция assumeTrue вызывается с выражением, имеющим значение false, тест будет остановлен и будет проигнорирован, что, я предполагаю, является тем, что вам нужно, если тест выполняется на устройстве до SDK 23.

0
Edison Spencer

GrantPermissionRule находится в библиотеке поддержки тестирования Android , которую вы можете использовать в своих тестах для предоставления разрешения перед началом любых тестов.

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.CAMERA, Android.Manifest.permission.ACCESS_FINE_LOCATION);
0
NSK

Я реализовал решение, которое использует классы-обертки, переопределяя и конфигурируя варианты сборки. Решение довольно длинное для объяснения и находится здесь: https://github.com/ahasbini/AndroidTestMockPermissionUtils .

Он еще не упакован в SDK, но основная идея состоит в том, чтобы переопределить функциональные возможности ContextWrapper.checkSelfPermission и ActivityCompat.requestPermissions для манипуляции и вернуть ложные результаты, обманывая приложение в различных сценариях, которые должны быть протестированы, например: разрешение было отклонено, следовательно, приложение запросило его и завершило работу с предоставленным разрешением. Этот сценарий будет происходить, даже если приложение все время имело разрешение, но идея заключается в том, что его обманули поддельные результаты переопределенной реализации.

Кроме того, в реализации есть класс TestRule с именем PermissionRule, который можно использовать в тестовых классах, чтобы легко имитировать все условия для плавного тестирования разрешений. Также можно сделать утверждения, например, убедившись, что приложение вызвало requestPermissions().

0
ahasbini