Android Marshmallow: проверить разрешения с помощью Espresso?
Новая схема разрешений, введенная Android Marshmallow, требует проверки определенных разрешений во время выполнения, что подразумевает необходимость предоставления разных потоков в зависимости от того, отрицает ли пользователь или разрешает доступ.
Как мы используем Espresso для запуска автоматических тестов пользовательского интерфейса в нашем приложении, как мы можем макетировать или обновлять состояние разрешений для тестирования разных сценариев?
Ответы
Ответ 1
В новом выпуске библиотеки поддержки тестирования 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
должно использоваться для того, чтобы избежать java.lang.Exception: The @Rule 'permissionRule' must be public.
Больше информации здесь.
Ответ 2
Принятый ответ на самом деле не проверяет диалог разрешений; это просто обходит это. Таким образом, если по какой-либо причине диалоговое окно разрешений завершится неудачно, ваш тест даст ложный зеленый цвет. Я рекомендую нажать кнопку "дать разрешения", чтобы проверить поведение всего приложения.
Посмотрите на это решение:
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 проверить его, потому что мы будем поддерживать это релиз за выпуском.
Ответ 3
Попробуйте такой статический метод, когда ваш телефон находится на английском языке:
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 ");
}
}
}
}
Я нашел его here
Ответ 4
Вы можете предоставить разрешения перед запуском теста с чем-то вроде:
@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...
, процесс будет убит.
Ответ 5
На самом деле есть два способа сделать это, я знаю до сих пор:
- Предоставьте разрешение с помощью команды adb перед началом тестирования (документация):
adb shell pm grant "com.your.package" android.permission.your_permission
- Вы можете щелкнуть по диалоговому окну разрешения и установить разрешение с помощью UIAutomator (документация). Если ваши тесты написаны с помощью Espresso для Android, вы можете легко скомбинировать шаги Espresso и UIAutomator в одном тесте.
Ответ 6
Вы можете легко достичь этого, предоставив разрешение перед началом теста. Например, если вы должны использовать камеру во время тестового прогона, вы можете предоставить разрешение следующим образом
@Before
public void grantPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getInstrumentation().getUiAutomation().executeShellCommand(
"pm grant " + getTargetContext().getPackageName()
+ " android.permission.CAMERA");
}
}
Ответ 7
ЭСПРЕССО ОБНОВЛЕНИЕ
Эта единственная строка кода дает немедленное действие каждому разрешению, указанному в качестве параметра в методе предоставления. Другими словами, приложение будет обрабатываться так, как если бы разрешения уже были предоставлены - больше никаких диалогов
@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/
Ответ 8
Я отключил и восстановил масштаб анимации до и после тестов с использованием эспрессо и adb, например здесь,
и кажется, что он действителен для M-разрешений, так как Stony Wang делает здесь и Denys ответил.
Ответ 9
Я знаю, что ответ был принят, однако, вместо предложения if
, которое было предложено снова и снова, еще одним более элегантным подходом было бы сделать следующее в фактическом тесте, который вы хотите использовать для конкретной версии OS:
@Test
fun yourTestFunction() {
Assume.assumeTrue(Build.VERSION.SDK_INT >= 23)
// the remaining assertions...
}
Если функция assumeTrue
вызывается с выражением, вычисляющим значение false, тест останавливается и игнорируется, и я предполагаю, что вы хотите, если тест выполняется на устройстве pre SDK 23.
Ответ 10
Я реализовал решение, которое использует классы-обертки, переопределяя и конфигурируя варианты сборки. Решение довольно длинное для объяснения и находится здесь: https://github.com/ahasbini/AndroidTestMockPermissionUtils.
Он еще не упакован в SDK, но основная идея состоит в том, чтобы переопределить функциональные возможности ContextWrapper.checkSelfPermission
и ActivityCompat.requestPermissions
для манипулирования и вернуть имитированные результаты, обманывая приложение в различных сценариях, которые должны быть протестированы, как: разрешение было отклонено, следовательно, приложение отказано просил об этом и закончил с предоставленным разрешением. Этот сценарий будет происходить, даже если приложение все время имело разрешение, но идея заключается в том, что его обманули поддельные результаты переопределяющей реализации.
Кроме того, реализация имеет TestRule
называемый классом PermissionRule
который можно использовать в тестовых классах, чтобы легко имитировать все условия для TestRule
тестирования разрешений. Также можно сделать утверждения, например, убедившись, что приложение requestPermissions()
.
Ответ 11
В библиотеке поддержки тестирования Android есть GrantPermissionRule, который вы можете использовать в своих тестах для предоставления разрешения перед началом любых тестов.
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION);
Ответ 12
Спасибо @niklas за решение. В случае, если кто-то хочет предоставить несколько разрешений в Java:
@Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA);