Зефир Android: Тестовые полномочия с Эспрессо?

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

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

62
задан 26 November 2015 в 06:06

11 ответов

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

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION);

решение

@get:Rule var permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION)

@get:Rule Kotlin должно использоваться для предотвращения [еще 113] информация здесь .

78
ответ дан 31 October 2019 в 13:13

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

Взглянули на это решение:

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 к Бариста , наш инструмент выше Эспрессо и UiAutomator для создания инструментальных тестов зелеными: https://github.com/SchibstedSpain/Barista проверяет его, потому что мы поддержим его выпуск выпуском.

37
ответ дан 31 October 2019 в 13:13

Можно дать разрешения, прежде чем тест будет запущен с чем-то как:

@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..., процесс уничтожается.

20
ответ дан 31 October 2019 в 13:13

Дайте попытку с таким статическим методом, когда Ваш телефон будет на английской локали:

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
ответ дан 31 October 2019 в 13:13

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

@Before
public void grantPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        getInstrumentation().getUiAutomation().executeShellCommand(
                "pm grant " + getTargetContext().getPackageName()
                        + " android.permission.CAMERA");
    }
}
7
ответ дан 31 October 2019 в 13:13

На самом деле существует 2 способа сделать это, я знаю до сих пор:

  1. Grant разрешение с помощью adb команду, прежде чем тест запускается ( документация ):

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

  1. можно нажать на диалоговое окно разрешения и установить разрешение с помощью UIAutomator ( документация ). Если Ваши тесты записаны с Эспрессо для андроида, можно объединить Эспрессо и шаги UIAutomator в одном тесте легко.
11
ответ дан 31 October 2019 в 13:13

ОБНОВЛЕНИЕ ЭСПРЕССО

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

@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
ответ дан 31 October 2019 в 13:13

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

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

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

0
ответ дан 31 October 2019 в 13:13

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

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

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

0
ответ дан 31 October 2019 в 13:13

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

@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION);
0
ответ дан 31 October 2019 в 13:13

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

 @Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.CAMERA);
0
ответ дан 31 October 2019 в 13:13

Другие вопросы по тегам:

Похожие вопросы: