Android Marshmallowによって導入された新しい許可スキームでは、実行時に特定の許可を確認する必要があります。これは、ユーザーがアクセスを拒否するか許可するかによって異なるフローを提供する必要があることを意味します。
Espressoを使用してアプリで自動UIテストを実行しているときに、さまざまなシナリオをテストするためにアクセス許可の状態をモックまたは更新するにはどうすればよいですか?
Android Testing Support Library 1. の新しいリリースでは、 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.
を使用する必要があります。詳細情報 こちら 。
受け入れられた答えは、実際に許可ダイアログをテストしません。単にバイパスします。そのため、何らかの理由でアクセス許可ダイアログが失敗した場合、テストは偽の緑色になります。実際に「許可を与える」ボタンをクリックして、アプリの動作全体をテストすることをお勧めします。
このソリューションをご覧ください:
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に追加しました。インストゥルメンタルテストは緑です。 https://github.com/SchibstedSpain/Barista リリースごとにメンテナンスするため、チェックしてください。
お使いの携帯電話が英語ロケールにある場合、そのような静的な方法で試してみてください:
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 ");
}
}
}
}
見つけました こちら
次のような方法で、テストを実行する前にアクセス許可を付与できます。
@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...
プロセスは強制終了されます。
実際、これを行うには2つの方法があります。
adb Shell pm grant "com.your.package" Android.permission.your_permission
テストを開始する前に許可を与えることで、これを簡単に達成できます。たとえば、テスト実行中にカメラを使用することになっている場合、次のように許可を与えることができます
@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
この1行のコードは、grantメソッドのパラメーターとしてリストされているすべての許可を即時に許可します。つまり、アクセス許可が既に付与されているかのようにアプリが処理されます-これ以上のダイアログはありません
@Rule @JvmField
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION)
そしてグラドル
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/
@niklasのソリューションに感謝します。 Javaで複数のアクセス許可を付与しようとしている場合:
@Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA);
私は答えが受け入れられたことを知っていますが、何度も繰り返し提案されているif
ステートメントの代わりに、別のよりエレガントなアプローチは、特定のバージョンの実際のテストで以下を実行することですOS:
@Test
fun yourTestFunction() {
Assume.assumeTrue(Build.VERSION.SDK_INT >= 23)
// the remaining assertions...
}
assumeTrue
関数がfalseと評価される式で呼び出された場合、テストは停止して無視されます。これは、SDK 23より前のデバイスでテストが実行されている場合に必要なものであると思われます。
Android Testing Support LibraryにGrantPermissionRuleがあります。これをテストで使用して、テストを開始する前に許可を与えることができます。
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Android.Manifest.permission.CAMERA, Android.Manifest.permission.ACCESS_FINE_LOCATION);
ラッパークラスを活用し、バリアント構成をオーバーライドおよびビルドするソリューションを実装しました。ソリューションは説明するのに非常に長く、ここにあります: https://github.com/ahasbini/AndroidTestMockPermissionUtils 。
SDKにはまだパックされていませんが、主なアイデアは、操作される_ContextWrapper.checkSelfPermission
_および_ActivityCompat.requestPermissions
_の機能をオーバーライドして、テストされるさまざまなシナリオにアプリをだまして模擬的な結果を返すことです。拒否されたため、アプリはそれを要求し、許可を得て終了しました。このシナリオは、アプリにずっと許可があったとしても発生しますが、アイデアは、オーバーライドする実装からの模擬結果によってtrickされたということです。
さらに、実装にはTestRule
クラスと呼ばれるPermissionRule
クラスがあり、これをテストクラスで使用して、すべての条件を簡単にシミュレートして、アクセス許可をシームレスにテストできます。また、たとえばアプリがrequestPermissions()
を呼び出したことを確認するようにアサーションを作成することもできます。