Le nouveau schéma d'autorisations introduit par Android Marshmallow requiert la vérification d'autorisations spécifiques lors de l'exécution, ce qui implique la nécessité de fournir des flux différents selon que l'utilisateur refuse ou autorise l'accès.
Comme nous utilisons Espresso pour exécuter des tests d’interface utilisateur automatisés sur notre application, comment pouvons-nous nous moquer ou mettre à jour l’état des autorisations afin de tester différents scénarios?
Avec la nouvelle version de Android Testing Support Library 1.0 , il existe un GrantPermissionRule que vous pouvez utiliser dans vos tests pour accorder une autorisation avant de commencer les tests.
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION);
La réponse acceptée ne teste pas réellement la boîte de dialogue des autorisations; il le contourne simplement. Ainsi, si la boîte de dialogue des autorisations échoue pour une raison quelconque, votre test donnera un faux vert. Je vous encourage à cliquer sur le bouton "donner des autorisations" pour tester le comportement de l'application dans son ensemble.
Regardez cette solution:
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");
}
}
Retrouvez la classe entière ici: https://Gist.github.com/rocboronat/65b1187a9fca9eabfebbb1212d818a3c4
Soit dit en passant, cette réponse étant populaire, nous avons ajouté PermissionGranter
à Barista, notre outil situé au-dessus d’Expresso et de UiAutomator pour rendre les tests instrumentaux écologiques: https://github.com/SchibstedSpain/Barista vérifiez-le, car nous le maintiendrons publication par publication.
Essayez avec cette méthode statique lorsque votre téléphone est en langue anglaise:
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 ");
}
}
}
}
Je l'ai trouvé ici
Vous pouvez accorder des autorisations avant que le test soit exécuté avec quelque chose comme:
@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");
}
}
Mais vous ne pouvez pas révoquer. Si vous essayez pm reset-permissions
ou pm revoke...
, le processus est tué.
En fait, il y a 2 façons de le faire que je connaisse jusqu'à présent:
adb Shell pm grant "com.your.package" Android.permission.your_permission
Vous pouvez y parvenir facilement en accordant une autorisation avant de commencer le test. Par exemple, si vous êtes censé utiliser l'appareil photo pendant l'exécution du test, vous pouvez accorder l'autorisation comme suit
@Before
public void grantPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getInstrumentation().getUiAutomation().executeShellCommand(
"pm grant " + getTargetContext().getPackageName()
+ " Android.permission.CAMERA");
}
}
MISE À JOUR ESPRESSO
Cette seule ligne de code accorde toutes les autorisations listées comme paramètre dans la méthode des subventions avec effet immédiat. En d'autres termes, l'application sera traité comme si les autorisations étaient déjà accordées - pas plus dialogues
@Rule @JvmField
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION)
et gradé
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"
...
}
référence: https://www.kotlindevelopment.com/runtime-permissions-espresso-done-right/
Merci @niklas pour la solution. Si quelqu'un cherche à accorder plusieurs autorisations en Java:
@Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA);
Je sais qu'une réponse a été acceptée, cependant, au lieu de la déclaration if
qui a été suggérée maintes et maintes fois, une autre approche plus élégante consisterait à effectuer les opérations suivantes dans le test réel souhaité pour une version spécifique du système d'exploitation:
@Test
fun yourTestFunction() {
Assume.assumeTrue(Build.VERSION.SDK_INT >= 23)
// the remaining assertions...
}
Si la fonction assumeTrue
est appelée avec une expression évaluée à false, le test s’arrête et est ignoré, ce que je suppose comme étant ce que vous voulez si le test est exécuté sur un périphérique pré-SDK 23.
Il y a GrantPermissionRule dans Android Testing Support Library , que vous pouvez utiliser dans vos tests pour accorder une autorisation avant de commencer des tests.
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.CAMERA, Android.Manifest.permission.ACCESS_FINE_LOCATION);
J'ai implémenté une solution qui exploite les classes wrapper, redéfinit et construit les variantes de configuration. La solution est assez longue à expliquer et se trouve ici: https://github.com/ahasbini/AndroidTestMockPermissionUtils .
Il n'est pas encore emballé dans un sdk mais l'idée principale est de remplacer les fonctionnalités de ContextWrapper.checkSelfPermission
et ActivityCompat.requestPermissions
à manipuler et à renvoyer les résultats fictifs capturant l'application dans les différents scénarios à tester, comme par exemple: l'autorisation a été refusée avec la permission accordée. Ce scénario se produira même si l'application avait l'autorisation depuis le début, mais l'idée est qu'il a été trompé par les résultats simulés de l'implémentation prépondérante.
De plus, l'implémentation a une classe TestRule
appelée PermissionRule
qui peut être utilisée dans les classes de test pour simuler facilement toutes les conditions permettant de tester les autorisations de manière transparente. Des affirmations peuvent également être faites, comme s’assurer que l’application a appelé requestPermissions()
par exemple.