I'd like to write an instrumented test to verify the behaviour of an app that requests location updates using the FusedLocation API on API23+.
I have some requirements:
The test must run in an emulator (AVD) because I'd like the tests to run in a continuous integration service like Travis CI or circle CI.
I want to test that the Marshmallow permissions request dialog properly pops-up using UI Automator.
I want to ensure my code works by checking the Location object returned by requestLocationUpdates() using assertions.
Since testing on an emulated device is a requirement we must then use FusedLocation.setMockLocation() in order to get a location or the requestLocationUpdates() will not yield any results.
Until now I have faced these problems:
Both setMockMode() and setMockLocation() require location permission: this means that I have to request the location permission in my test code and once my code under test reaches the requestLocationUpdates() call it won't request permission again (because it already has it) thereby not letting me test the permission request dialog with UI Automator.
setMockLocation() requires manually setting "Allow mock locations" in developer options so the Continuous Integration will fail because a new emulator is created every build and will have "Allow mock locations" disabled by default.
It seems to my I've reached a dead end. Please prove me wrong!
Related
For instrumented tests of location services I need mocked locations. But the current concept from Android seems to be not very practical.
In order to be allowed to use mocked locations the test-package also needs the permission android.permission.ACCESS_MOCK_LOCATION. When added to a debug-manifest I get the hint, that this permission will only be granted to System-Apps. I have to add tools:ignore="ProtectedPermissions" to the permission to suppress this warning. IMHO it makes no sense to issue such a warning for a property that is necessary for such tests.
Then I need to select this test-package as mock-location provider for the test-device. Acceptable for a manual test. But do I really have to manually select this setting for every device I want to test my code on? (What about this firebase-test on a farm of test devices? There I can not make this setting.)
And what if I have more than one app that tests mocked location? Currently I can not test both packages on the same device.
Or am I missing something?
I am talking about the quality issue (bug) that an Android app needs a permission that is declared in the Manifest, but fails to request it from the user at the appropriate time and executes the code without the necessary permission. This was not possible in older Android versions (user accepts all permissions in bulk), but seems to be possible when using newer versions that copy Apple in most regards.
At least during testing one can start background services and use bluetooth without any alert by Google popping up. Is that different for apps in production?
Does the app crash with an Exception?
Does the code get executed?
Does the app get rejected in review? (Always?)
Does the app get delisted from the store?
Does it depend on Android's Version?
I deal with an age old app that has bluetooth discovery code to find and connect to dedicated hardware, that is rarely used via a cordova plugin triggered by content. There is old altbeacon code potentially activated that may even need access background location (https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions). It will take some time to get this dead code up to quality. Definitely more time than the week we have.
Does the app crash with an Exception?
yes if you try to have operations depends on returned date witch is null
Does the code get executed?
code will execute with exceptions because data access denied you can check if permission granted or not and add scenario for each state
Does the app get rejected in review? (Always?) not sure but with crashes there is high potential to get rejected
Does the app get delisted from the store?
depends on why and how you are using data
Does it depend on Android's Version?
yes access data and permissions changing point is android oreo
My tests with Bluetooth permissions revealed the following: Required permissions are BLUETOOTH_ADMIN, BLUETOOTH and for VERSION_CODES.Q additionally Manifest.permission.ACCESS_BACKGROUND_LOCATION (see: https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions).
BLUETOOTH_ADMIN, BLUETOOTH do not show any system alert-dialogue to the user. In Android Q+ if you fail to check for the required ACCESS_BACKGROUND_LOCATION permission, nothing happens and your code executes without exception (mine did execute an UART command on hardware with Samsung tablet). The app passed review although the check is missing (of course I will fix that ASAP).
Note: the doc is ambiguous and states: "Services running on Android 10 and higher cannot discover Bluetooth devices unless they have the ACCESS_BACKGROUND_LOCATION permission." Probably general scanning while the app is active could be allowed. In that case missing exception would be explained.
I have an android app that shouldn't request location in background. But I do see a reminder.
Most probably it's some library, can be facebook sdk or similar. How can I find, which one?
The best way would be to crash internal builds, then I will get stacktrace. But I haven't found strict mode settings for background location access.
Any recommendations?
I´m making an Android app.
So I´m starting with some instrumentation testing where I want to start with data enabled and location disabled and I want to test that a dialog asking me to enable location appears.
For my second test I want to start with data disabled and location enabled and I want to test that a dialog asking me to enable data appears.
How can I manipulate the location and data for an instrumentation test?
Thanks in advance.
If you do separation of the concerns then you have special class or classes for checking if some user settings are enabled/disabled. So you can mock it in test and check that dialogues are shown.
However, to test the class that checks user settings you need to manipulate with emulator/device directly. Check Is there an ADB command to enable/disable mobile data?(Rooted Device) or https://github.com/linkedin/test-butler
I work in QA for an company that helps market applications. Currently I have been tasked to ensure location dependent apps function if correctly (ie if im in russia the app displays the russian content and if i change to us the app updates to the us content)
I have tried numerous items to accomplish this but get no where.
What i have tried:
Proxy. Setting this up via wifi to several locations. Both the app and the device still show my current location.
Apps: I have tried all of the following apps and they all give the same result as above.
Fake Location
AutoProxy
Fake GPS
I have enabled developer mode on the devices, and have ensured that "Mock Locations" is checked.
Use case 1:
A developer whats us to test his app which is only available in england. Google Play still sees me in US
Use case 2:
A developer releases a game where the background changes based on your location if i cant force the location change I cant verify this feature works.
Im guessing the fails so far are due to the fact that the location being called in our test apps is network location not GPS?
Any help would be awesome. Even if you could just point me in a direction.
Thank you Greatly
J
Update:
Ok, Thanks to the answers about google play and mock locations. So with those in mind lets think about it from another perspective. If the app is not calling for mock location, Is there anyway to force a mock location override? im trying to cover all the bases here, One app for sure does not use this method, so I still need to find a way around.
depending on how they are calling for the location, I would think (remember im knew here) that using a proxy would work, however as stated above, i'm not getting anywhere there either. Did try a few free proxy's from hidemyass but even the browser wouldn't work with them.
Yes, network location does not get faked by mock location providers. I don't know why not, but it only fakes GPS. In addition, your app has to request the MOCK permission to get it. If it doesn't have this permission, setting a mock location will not actually fake anything to the app. This is for security purposes, so a malicious app can't start broadcasting the wrong location to the phone.