Как написать эспрессо-тесты, которые проверяют местоположение GPS и использовать их в Google Testlab?

Я записал эспрессо-тест с помощью Espresso Recorder. Я хочу проверить некоторые изменения местоположения в моем приложении.

В настоящее время я издеваюсь с этим кодом:

LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy( Criteria.ACCURACY_FINE );

String mocLocationProvider = LocationManager.GPS_PROVIDER;//lm.getBestProvider( criteria, true );

lm.addTestProvider(mocLocationProvider, false, false,
        false, false, true, true, true, 0, 5);
lm.setTestProviderEnabled(mocLocationProvider, true);

Location loc = new Location(mocLocationProvider);
Location mockLocation = new Location(mocLocationProvider); // a string
mockLocation.setLatitude(-26.902038);  // double
mockLocation.setLongitude(-48.671337);
mockLocation.setAltitude(loc.getAltitude());
mockLocation.setTime(System.currentTimeMillis());
mockLocation.setAccuracy(1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
lm.setTestProviderLocation( mocLocationProvider, mockLocation);

Я также добавил разрешение в файл отладочного манифеста:

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

Но, к сожалению, я все еще получаю исключение безопасности:

java.lang.SecurityException: mypackage.test from uid not allowed to perform MOCK_LOCATION

Я хочу запустить записанный контрольный пример с проверенным местоположением в Google Firebase Test Lab. Как я могу решить эту проблему?

2 ответа

По сути, вы должны включить приложение в настройках разработчика (выбрать приложение для определения местоположения). Поскольку вы не можете управлять устройствами на Google Plateform, вы должны использовать команду ADB, чтобы включить его.

appops set {yourPackageName} android:mock_location allow

Как, например, это то, что я делаю в функции @before для моих проверок местоположения:

@Before
fun grantPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        with(getInstrumentation().uiAutomation) {
            ...
            executeShellCommand("appops set " + InstrumentationRegistry.getTargetContext().packageName + " android:mock_location allow")
            Thread.sleep(1000)
            ...
        }
    }
}

Основываясь на этом подходе, обратите внимание, что вы также можете создать фрагмент для своей задачи gradle, чтобы он автоматически выполнялся на рабочей станции, если вы подключаете любое новое устройство. См., Например: Как установить Allow Mock Location на устройстве Android перед выполнением AndroidTest с помощью uiautomator и эспрессо?

Надеюсь, это поможет!

MrAurelien предложил отличное решение. Но лучше реализовать это немного по-другому.

Thread.sleep(1000)делает ваши тесты более медленными и ненадежными. Вот другая версия, которая работает стабильно.

      @Before
fun grantPermission() {
    instrumentation.uiAutomation.executeShellCommandBlocking(
        "appops set ${appContext.packageName} android:mock_location allow"
    )
}

executeShellCommandBlocking— это пользовательская функция utils, которая ожидает завершения команды appops .

      fun UiAutomation.executeShellCommandBlocking(command: String) {
    val output = executeShellCommand(command)
    FileInputStream(output.fileDescriptor).use { it.readBytes() }
}

Мы используем это решение в Mapbox Android Navigation SDK.

Другие вопросы по тегам