Handling Android Runtime permissions in UI Tests in SUSI.AI Android

With the introduction of Marshmallow (API Level 23), in SUSI.AI it was needed to ensure that:

  • It was verified if we had the permission that was needed, when required
  • The user was requested to grant permission, when it deemed appropriate
  • The request (empty states or data feedback) was correctly handled within the UI to represent the outcome of being granted or denied the required permission

You might have written UI tests. What about instances where the app needs the user’s permissions, like allow the app to access contacts on the device, for the tests to run? Would the tests pass when the test is run on Android 6.0+ devices?
And, can Espresso be used to achieve this? Unfortunately, Espresso doesn’t have the ability to access components from outside of the application package. So, how to handle this?
There are two approaches to handle this :
1) Using the UI Automator
2) Using the GrantPermissionRule

Let us have a look at both of these approaches in detail :

Using UI Automator to Handle Runtime Permissions on Android for UI Tests :

UI Automator is a UI testing framework suitable for cross-app functional UI testing across system and installed apps. This framework requires Android 4.3 (API level 18) or higher.
The UI Automator testing framework provides a set of APIs to build UI tests that perform interactions on user apps and system apps. The UI Automator APIs allows you to perform operations such as opening the Settings menu or the app launcher in a test device. This testing framework is well-suited for writing black box-style automated tests, where the test code does not rely on internal implementation details of the target app.

The key features of this testing framework include the following :

  • A viewer to inspect layout hierarchy. For more information, see UI Automator Viewer.
  • An API to retrieve state information and perform operations on the target device. For more information, see Accessing device stateAPIs that support cross-app UI testing. For more information, see UI Automator APIs.
  • Unlike Espresso, UIAutomator can interact with system applications which means that you’ll be able to interact with the permissions dialog, if needed.

    So, how to do this? Well, if you want to grant a permission in a UI test then you need to find the corresponding UiObject that you wish to click on. In our case, the permissions dialog box is the UiObject. This object is a representation of a view – it is not bound to the view but contains information to locate the matching view at runtime, based on the properties of the UiSelector instance within it’s constructor. A UiSelector instance is an object that declares elements to be targeted by the UI test within the layout. You can set various properties such as a text value, class name or content-description, for this UiSelector instance.
    So, once you have your UiObject (the permissions dialog), you can determine which option you want to select and then use click( ) method to grant/deny permission access.

fun allowPermissionsIfNeeded() {
         iIf (BUILD.VERSION.SDK_INT >= 23){
                   var allowPermissions : UiObject = mDevice
                                       .findObject(UiSelector( ).text("ALLOW"))
                   if(allowPermissions.exists( )) {
                             try {
                                       allowPermissions.click( )
                             } catch (e : UiObjectNotFoundException) {
                                       Log.e(TAG, "There is no permission dialog to interact with", e)
                             }
                   } 
         }
}

Similarly, you can also handle “DENY” approach.

So, this is how you can use UI Automator to handle Android runtime permissions for UI testing. Now, let us have a look at the other and a newer approach :

Using GrantPermissionRule to Handle Runtime Permissions on Android for UI Tests :

GrantPermissionRule is used to grant runtime permissions to avoid the permission dialog from showing up and blocking the UI of the app. In this approach, permissions can only be requested for API level 23 (Android M) or higher. All you need to do is to add the following rule to your UI test :

@Rule 
public GrantPermissionRule mRuntimePermissionRule =     
           GrantPermissionRule.grant(android.Manifest
.permission.ACCESS_FINE_LOCATION);

ACCESS_FINE_LOCATION (in the above code) can be replaced by any other permission that your app requires.

This would be also be implemented in the SUSI.AI Android app for UI tests. Unit tests and UI tests form an integral part of a good software. Hence, you need to write quality tests for your projects to detect and fix bugs and flaws easily and conveniently.

Resources

 

Continue ReadingHandling Android Runtime permissions in UI Tests in SUSI.AI Android

UI Espresso Test Cases for Phimpme Android

Now we are heading toward a release of Phimpme soon, So we are increasing the code coverage by writing test cases for our app. What is a Test Case? Test cases are the script against which we run our code to test the features implementation. It is basically contains the output, flow and features steps of the app. To release app on multiple platform, it is highly recommended to test the app on test cases.

For example, Let’s consider if we are developing an app which has one button. So first we write a UI test case which checks whether a button displayed on the screen or not? And in response to that it show the pass and fail of a test case.

Steps to add a UI test case using Espresso

Espresso testing framework provides APIs to simulate user interactions. It has a concise API. Even, now in new Version of Android Studio, there is a feature to record Espresso Test cases. I’ll show you how to use Recorder to write test cases in below steps.

  • Setup Project Directory

Android Instrumentation tests must be placed in androidTest directory. If it is not there create a directory in app/src/androidTest/java…

  • Write Test Case

So firstly, I am writing a very simple test case, which checks whether the three Bottom navigation view items are displayed or not?

Espresso Testing framework has basically three components:

ViewMatchers

Which helps to find the correct view on which some actions can be performed E.g. onView(withId(R.id.navigation_accounts). Here I am taking the view of accounts item in Bottom Navigation View.

ViewActions

It allows to perform actions on the view we get earlier. E.g. Very basic operation used is click()

ViewAssertions

It allows to assert the current state of the view E.g. isDisplayed() is an assertion on the view we get. So a basic architecture of an Espresso Test case is

onView(ViewMatcher)       
 .perform(ViewAction)     
   .check(ViewAssertion);

We can also Use Hamcrest framework which provide extra features of checking conditions in the code.

Setup Espresso in Code

Add this in your application level build.gradle

// Android Testing Support Library's runner and rules
androidTestCompile "com.android.support.test:runner:$rootProject.ext.runnerVersion"
androidTestCompile "com.android.support.test:rules:$rootProject.ext.rulesVersion"

// Espresso UI Testing dependencies.
androidTestCompile "com.android.support.test.espresso:espresso-core:$rootProject.ext.espressoVersion"
androidTestCompile "com.android.support.test.espresso:espresso-contrib:$rootProject.ext.espressoVersion"
  • Use recorder to write the Test Case

New recorder feature is great, if you want to set up everything quickly. Go to the Run → Record Espresso Test in Android Studio.

It dumps the current User Interface hierarchy and provide the feature to assert that.

You can edit the assertions by selecting the element and apply the assertion on it.

Save and Run the test cases by right click on Name of the class. Run ‘Test Case name’

Console will show the progress of Test case. Like here it is showing passed, it means it get all the view hierarchy which is required by the Test Case.

Resources

Continue ReadingUI Espresso Test Cases for Phimpme Android