varios studio permission permisos pedir onrequestpermissionsresult example code android permissions android-espresso android-6.0-marshmallow

studio - Android Marshmallow: ¿Permisos de prueba con Espresso?



request camera permission android (11)

Con la nueva versión de Android Testing Support Library 1.0 , hay una GrantPermissionRule que puede usar en sus pruebas para otorgar un permiso antes de comenzar cualquier prueba.

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

Solución de Kotlin

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

@get:Rule debe usarse para evitar java.lang.Exception: The @Rule ''permissionRule'' must be public. Más información here .

El nuevo esquema de permisos introducido por Android Marshmallow requiere la verificación de permisos específicos en tiempo de ejecución, lo que implica la necesidad de proporcionar diferentes flujos dependiendo de si el usuario niega o permite el acceso.

A medida que utilizamos Espresso para ejecutar pruebas automatizadas de IU en nuestra aplicación, ¿cómo podemos burlarnos o actualizar el estado de los permisos para probar diferentes escenarios?


En realidad, hay 2 formas de hacer esto que sé hasta ahora:

  1. Otorgue el permiso usando el comando adb antes de que comience la prueba ( documentation ):

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

  1. Puede hacer clic en el diálogo de permiso y establecer el permiso usando UIAutomator ( documentation ). Si sus pruebas están escritas con Espresso para Android, puede combinar fácilmente los pasos de Espresso y UIAutomator en una prueba.

Gracias @niklas por la solución. En caso de que alguien quiera otorgar múltiples permisos en Java:

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


Hay GrantPermissionRule en la Biblioteca de soporte de pruebas de Android , que puede usar en sus pruebas para otorgar un permiso antes de comenzar cualquier prueba.

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


Implementé una solución que aprovecha las clases de envoltura, anulando y construyendo configuraciones de variantes. La solución es bastante larga de explicar y se encuentra aquí: https://github.com/ahasbini/AndroidTestMockPermissionUtils .

Todavía no está empaquetado en un SDK, pero la idea principal es anular las funcionalidades de ContextWrapper.checkSelfPermission y ActivityCompat.requestPermissions para manipular y devolver resultados simulados engañando a la aplicación en los diferentes escenarios para probar como: el permiso fue denegado por lo tanto, la aplicación lo solicitó y terminó con el permiso otorgado. Este escenario ocurrirá incluso si la aplicación tuvo el permiso todo el tiempo, pero la idea es que fue engañada por los resultados burlados de la implementación principal.

Además, la implementación tiene una clase TestRule llamada PermissionRule que se puede usar en las clases de prueba para simular fácilmente todas las condiciones para probar los permisos sin problemas. También se pueden hacer afirmaciones, como asegurarse de que la aplicación haya llamado requestPermissions() por ejemplo.


La respuesta aceptada en realidad no prueba el diálogo de permisos; solo lo pasa por alto. Entonces, si el cuadro de diálogo de permisos falla por alguna razón, su prueba dará un verde falso. Realmente recomiendo hacer clic en el botón "otorgar permisos" para probar el comportamiento completo de la aplicación.

Echa un vistazo a esta solución:

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

Encuentra toda la clase aquí: https://gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

Por cierto, como esta respuesta ha sido popular, agregamos PermissionGranter a Barista , nuestra herramienta por encima de Espresso y UiAutomator para que las pruebas instrumentales sean ecológicas: https://github.com/SchibstedSpain/Barista compruébelo, porque lo mantendremos se lanza por lanzamiento.


Pruebe con este método estático cuando su teléfono esté en inglés:

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

Lo encontre here


Puede lograr esto fácilmente otorgando permiso antes de comenzar la prueba. Por ejemplo, si se supone que debe usar la cámara durante la ejecución de la prueba, puede otorgar el permiso de la siguiente manera

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


Puede otorgar permisos antes de ejecutar la prueba con algo como:

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

Pero no puedes revocarlo. Si prueba pm reset-permissions o pm revoke... el proceso finaliza.


Sé que se ha aceptado una respuesta, sin embargo, en lugar de la declaración if que se ha sugerido una y otra vez, otro enfoque más elegante sería hacer lo siguiente en la prueba real que desea para una versión específica del sistema operativo:

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

Si se assumeTrue función assumeTrue con una expresión que se evalúa como falsa, la prueba se detendrá e ignorará, lo que supongo es lo que desea en caso de que la prueba se ejecute en un dispositivo anterior al SDK 23.


ACTUALIZACIÓN DE ESPRESSO

Esta única línea de código otorga todos los permisos enumerados como parámetro en el método de concesión con efecto inmediato. En otras palabras, la aplicación será tratada como si los permisos ya estuvieran otorgados, no más diálogos

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

y 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" ... }

referencia: https://www.kotlindevelopment.com/runtime-permissions-espresso-done-right/