it-swarm.com.de

Android Marshmallow: Testberechtigungen mit Espresso?

Das von Android Marshmallow eingeführte neue Berechtigungsschema erfordert die Prüfung bestimmter Berechtigungen zur Laufzeit. Dies bedeutet, dass unterschiedliche Flüsse bereitgestellt werden müssen, je nachdem, ob der Benutzer den Zugriff verweigert oder zulässt.

Wie können wir bei Verwendung von Espresso zum Ausführen automatisierter UI-Tests in unserer App den Status der Berechtigungen nachahmen oder aktualisieren, um verschiedene Szenarien zu testen?

53
argenkiwi

Mit der neuen Version der Android Testing Support Library 1.0 gibt es eine GrantPermissionRule , die Sie in Ihren Tests verwenden können, um vor dem Starten von Tests eine Berechtigung zu erteilen.

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

Die akzeptierte Antwort testet den Berechtigungsdialog nicht wirklich. es umgeht es einfach. Wenn also das Berechtigungsdialogfeld aus irgendeinem Grund fehlschlägt, zeigt der Test ein falsches Grün. Ich ermutige eigentlich, auf die Schaltfläche "Berechtigungen erteilen" zu klicken, um das gesamte App-Verhalten zu testen.

Schauen Sie sich diese Lösung an:

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

Die gesamte Klasse finden Sie hier: https://Gist.github.com/rocboronat/65b1187a9fca9eabfebb5121d818a3c4

Da diese Antwort sehr beliebt war, haben wir PermissionGranter zu Barista hinzugefügt, unserem Werkzeug oberhalb von Espresso und UiAutomator, um instrumentelle Tests grün zu machen: https://github.com/SchibstedSpain/Barista check it out, da wir die Veröffentlichung durch Veröffentlichung beibehalten werden.

33
Roc Boronat

Versuchen Sie es mit einer solchen statischen Methode, wenn sich Ihr Telefon in der englischen Sprache befindet:

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

Ich habe es gefunden hier

29
riwnodennyk

Sie können Berechtigungen erteilen, bevor der Test ausgeführt wird.

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

Aber du kannst nicht widerrufen. Wenn Sie pm reset-permissions oder pm revoke... versuchen, wird der Prozess abgebrochen.

19
Jose Alcérreca

Eigentlich gibt es zwei Möglichkeiten, dies zu tun:

  1. Erteilen Sie die Berechtigung mit dem Befehl adb, bevor der Test startet ( documentation ):

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

  1. Sie können auf den Berechtigungsdialog klicken und die Berechtigung mit UIAutomator ( documentation ) festlegen. Wenn Ihre Tests mit Espresso für Android geschrieben wurden, können Sie die Schritte von Espresso und UIAutomator problemlos in einem Test kombinieren.
11
denys

Sie können dies leicht erreichen, indem Sie die Erlaubnis erteilen, bevor Sie den Test starten. Wenn Sie zum Beispiel die Kamera während des Testlaufs verwenden, können Sie die Berechtigung wie folgt erteilen

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

ESPRESSO UPDATE

Diese einzelne Codezeile gewährt jede Berechtigung, die als Parameter .__ aufgeführt ist. in der Grant-Methode mit sofortiger Wirkung. Mit anderen Worten, die App wird wie behandelt, wenn die Berechtigungen bereits erteilt wurden - nicht mehr Dialoge

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

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

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

3
murt

Danke @niklas für die Lösung. Für den Fall, dass jemand mehrere Berechtigungen in Java erteilen möchte:

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

Ich weiß, dass eine Antwort akzeptiert wurde. Statt der if-Anweisung, die immer wieder vorgeschlagen wurde, wäre ein eleganterer Ansatz die folgende Vorgehensweise im eigentlichen Test, den Sie für eine bestimmte Version des Betriebssystems wünschen:

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

Wenn die assumeTrue-Funktion mit einem Ausdruck aufgerufen wird, der den Wert false ergibt, wird der Test angehalten und ignoriert. Ich gehe davon aus, dass Sie das wollen, falls der Test auf einem Gerät vor dem SDK 23 ausgeführt wird.

0
Edison Spencer

In Android Testing Support Library gibt es die GrantPermissionRule, die Sie in Ihren Tests verwenden können, um vor dem Starten von Tests eine Berechtigung zu erteilen.

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

Ich habe eine Lösung implementiert, die Wrapper-Klassen nutzt, die Variantenkonfiguration überschreibt und erstellt. Die Lösung ist ziemlich lang zu erklären und ist hier zu finden: https://github.com/ahasbini/AndroidTestMockPermissionUtils .

Es ist noch nicht in einem SDK verpackt, aber die Hauptidee besteht darin, die Funktionalitäten von ContextWrapper.checkSelfPermission und ActivityCompat.requestPermissions zu überschreiben, die manipuliert werden sollen, und zurückgegebene Ergebnisse zurückzugeben, die die App in die verschiedenen Szenarien überführen, die getestet werden sollen: Die Berechtigung wurde abgelehnt und die Anwendung wurde beendet mit Erlaubnis. Dieses Szenario tritt auch dann auf, wenn die App die ganze Zeit über die Berechtigung hatte, die Idee ist jedoch, dass sie durch die simulierten Ergebnisse der überschreibenden Implementierung ausgetrickst wurde.

Darüber hinaus verfügt die Implementierung über eine TestRule-Klasse namens PermissionRule, die in den Testklassen verwendet werden kann, um auf einfache Weise alle Bedingungen zu simulieren, um die Berechtigungen nahtlos zu testen. Es können auch Zusicherungen gemacht werden, die beispielsweise sicherstellen, dass die App requestPermissions() aufgerufen hat.

0
ahasbini