Speed up testing - API alternative to device selection

This post shows you how to acquire a device id from the Perfecto API in order to use regular expressions on the deviceID field.

Utilizing regular expressions on the device id would enable you to filter out devices you have no desire of acquiring during your driver setup. These could be problem devices or devices you wish to leave available for other purposes. Below I'll show you how to achieve this using a mix of the deviceName capability and the Perfecto api for device list.

Below you will find the code used to send the request to the cloud

Copy
private String sendRequest(URL url) throws IOException {
        BufferedReader reader = null;
        StringBuilder stringBuilder=null;
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
           
                connection.setRequestMethod("GET");
            
                connection.setReadTimeout(15 * 1000);
                connection.connect();

                reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                stringBuilder = new StringBuilder();

                String line = null;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line + "\n");
                }

                int coden = connection.getResponseCode();
                if (coden > HttpURLConnection.HTTP_OK) {
                    handleError(connection);
                }

                return stringBuilder.toString();
           
    }

Below is a method which can be used to handle any errors returned by the API

Copy
private void handleError(HttpURLConnection connection) throws IOException {
        InputStream errorStream = connection.getErrorStream();
        InputStreamReader inputStreamReader = new InputStreamReader(errorStream, UTF_8);
        BufferedReader bufferReader = new BufferedReader(inputStreamReader);
        try {
            StringBuilder builder = new StringBuilder();
            String outputString;
            while ((outputString = bufferReader.readLine()) != null) {
                if (builder.length() != 0) {
                    builder.append("\n");
                }
                builder.append(outputString);
            }
            String response = builder.toString();
            throw new RuntimeException("Failed to call api. Reponse: " + response);
        } finally {
            bufferReader.close();
        }
    }

Next we setup the string values that we'll pass to the API for retrieving back a list of devices. We are using regular expressions here for all values. The "excludeDevice" list and the "androidModels" list is using an exclusion expression so anything listed will not be picked up. The models and versions list are using inclusion expressions.

Copy
String iPhoneModels="^(iPhone-5.*|iPhone-6.*)$"
String iPhoneVersions="9.0|9.0.1|9.1"
String iPhoneExcludeDevice="^(?!ABC|DEF|JKL)(^.*)"
String iPadModels="^(iPad 4|iPad Air|iPad 3)$"
String iPadVersions="9.0|9.0.1|9.1|8.4|8.3"
String iPadExcludeDevice="^(?!MNO|PQR|STU)(^.*)"
String androidModels="^(?!Nexus 7|Fire Phone|Galaxy Tab 2-10.*)(^.*)"
String androidOSVersions="5.1.1|5.0.1|5.0"
String androidExcludeDevice="^(?!VWX|YZA|BCD)(^.*)"

Lastly, the code for executing and connecting to the cloud using the Remote Web Driver

Copy
//setting the automation name to Perfecto        
capability.setCapability("automationName", scriptProperties.getProperty("PERFECTOFRAMEWORK"));
//setting browser name to empty since we're testing native app
capability.setCapability("browserName", "");

//setting base url for the api call
String deviceURL = cloud_scheme + "://" + cloud_host
                    + "/services/handsets?operation=list&inUse=false&reservedto=&status=connected&user=" + cloud_uname
                    + "&password=" + cloud_pwd;
            URL url = null;
            String deviceList = null;
            String tempDevice = null;
                //deviceType variable can be read from properties file
                //using the case statement to build out the models/versions/device list in the url
                switch (this.deviceType) {
                case "iPhone":
                    if (!iPhoneVersions.equals("")) {
                        deviceURL = deviceURL + "&osversion=" + iPhoneVersions;
                    }
                    if (!iPhoneModels.equals("")) {
                        deviceURL = deviceURL + "&model=" + iPhoneModels;
                    }
                    if (!iPhoneExclude.equals("")) {
                        deviceURL = deviceURL + "&deviceId=" + iPhoneExclude;
                    }
                    deviceURL = deviceURL + "&os=iOS";
                    break;
                case "iPad":
                    if (!iPadVersions.equals("")) {
                        deviceURL = deviceURL + "&osversion=" + iPadVersions;
                    }
                    if (!iPadModels.equals("")) {
                        deviceURL = deviceURL + "&model=" + iPadModels;
                    }
                    if (!iPadExclude.equals("")) {
                        deviceURL = deviceURL + "&deviceId=" + iPadExclude;
                    }
                    deviceURL = deviceURL + "&os=iOS";
                    break;
                case "Android":
                    if (!androidVersions.equals("")) {
                        deviceURL = deviceURL + "&osversion=" + androidVersions;
                    }
                    if (!androidModels.equals("")) {
                        deviceURL = deviceURL + "&model=" + androidModels;
                    }
                    if (!androidExclude.equals("")) {
                        deviceURL = deviceURL + "&deviceId=" + androidExclude;
                    }
                    deviceURL = deviceURL + "&os=Android";
                    break;
                default:
                    break;
                }
                //url encoding for spaces
                deviceURL = deviceURL.replace(" ", "%20");
                url = new URL(deviceURL);
                //retrieving the device list from the api
                deviceList = sendRequest(url);
                //grabbing the first device id from the response
                tempDevice = deviceList.split("<deviceId>")[1].split("</deviceId>")[0];
                //setting the retrieved deviceID for the device Name capability
                capability.setCapability("deviceName", tempDevice);

                //initializing the mobile driver
                mobiledriver = new RemoteWebDriver(gridURL, capability);