NV-Mobile Center Integration Sample for Appium Java Tests

You can integrate Network Virtualization with Mobile Center to run Appium scripts over a virtual network when testing your mobile application.

This code sample provides all of the Network Virtualization-specific code that you need to get started.

For example, to enable Network Virtualization to analyze your application's performance in these tests, you need to route the device’s HTTP/S traffic through the NV Test Manager host machine using the NV Proxy. This sample describes how to automatically configure the mobile device’s proxy settings to use the NV Proxy and install the NV Proxy certificate on an Android device. The code uses UI automation, so it is very device- and language-dependent. This sample also describes how to generate the NV Insights analysis report and the HAR file that can be used for load testing.

We tested this sample on several devices that run an English version of Android 7. This sample may not work as expected on your mobile device.

This section describes how the code works, with some details omitted. You can access the full Sample script for Appium test at the end of this section. Feel free to customize the sample Appium Java code displayed below according to your needs.

To configure the mobile device to use Network Virtualization:

  1. Define the required driver capabilities.

    URL mcServerUrl = new URL("http://" + MC_SERVER_IP + ":8080/wd/hub");
    RequiredCapabilities capabilities = getBaseCapabilities();
  2. Launch Chrome on the device (instead of the application under test) in preparation for installing the NV Proxy certificate using UI Automation.

    // Launch Chrome on the device
    capabilities.setCapability("appPackage", "com.android.chrome");
    capabilities.setCapability("appActivity", "com.google.android.apps.chrome.Main");        
  3. Connect the driver to Mobile Center and install the NV Proxy certificate.

    // Connect the driver to Mobile Center
    AndroidDriver<WebElement> driver = null;
    driver = new AndroidDriver<WebElement>(mcServerUrl, capabilities);
                                                    
    // Install the NV Proxy certificate
    installCertificate(driver);
  4. Configure the proxy settings of the connected WiFi network.

    // Configure proxy settings
    setWifiProxy(driver);

    The mobile device is now configured to use Network Virtualization.

    Although you can start running your code, this sample is designed to test the network impact on the application the first time the application is installed.

    To do this, you quit the current test and run a new test that is specific to the application.

  5. Prepare for the new, application-specific test.

    // Save the device name so that you can use the same device on the next Appium run from Mobile Center
    String deviceName = driver.getCapabilities().getCapability("deviceName").toString();
    
    // Quit the current Appium test
    driver.quit();
  6. Start the new test by installing the application on the same device as in the previous test.

    // Connect and start the new Network Virtualization test
    capabilities = getBaseCapabilities();
    capabilities.setCapability("appPackage", "com.Advantage.aShopping");
    capabilities.setCapability("appActivity", "com.Advantage.aShopping.SplashActivity");
    capabilities.setCapability("udid", deviceName);
  7. Specify the Network Virtualization network to use.

    // Select a network profile to use
    capabilities.setCapability("mc:net:profileName", NET_PROFILE_3G_POOR);
    driver = new AndroidDriver<WebElement>(mcServerUrl, capabilities);

    The test is now ready for the actual test code, but before running the test, clear the application cache.

  8. Clear the application cache and run the test.

    // Clear the application cache
    driver.resetApp();
    // Run the test
    runAdvantageAppScript(driver, "LAPTOPS");
  9. When the test finishes running, stop Network Virtualization and download the NV Insights report and HAR file.

    Object response= null;
    
    // Stop test and get report
    String fileName = "C:\\report.zip";
    response = driver.executeScript("mc:net:getReport");
    String base64Str = (String) response;
    byte[] bytes = Base64.getDecoder().decode(base64Str);
    IOUtils.write(bytes, new FileOutputStream(new File(fileName)));
                            
    // get HAR file
    fileName = "C:\\nv_har.zip";
    response = driver.executeScript("mc:net:getHAR");
    base64Str = (String) response;
    bytes = Base64.getDecoder().decode(base64Str);
    IOUtils.write(bytes, new FileOutputStream(new File(fileName)));
  10. (Optional) Remove the Network Virtualization settings from the device.

    // Clear proxy settings
    clearWifiProxy(driver);
                            
    // Remove proxy certificate
    removeCertificate(driver);

Sample script for Appium test

Here is the entire script with all of the details. You can copy the script to your testing environment and modify it as needed.

import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.time.Duration;
import java.util.Base64;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RequiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileBy;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.Activity;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;

public class ExampleAndroid {
                
                public static final String MC_SERVER_IP = "127.0.0.1";
                public static final String MC_SERVER_USER = "admin@default.com";
                public static final String MC_SERVER_PASSWORD = "******";
                public static final String NV_IP = "1.1.1.1";
                public static final String PROXY_IP = NV_IP;
                public static final String PROXY_PORT = "8888";
                
                public static final String DEVICE_PASSWORD = "****";
                public static final int ENTER_KEY = 66;
                
                public static final String CERT_NAME = "hpenv";
                public static final String CERT_FULL_NAME = "Hewlett Packard Enterprise";
                public static final String CERT_URL = NV_IP + ":8182/hpenv.cer";
                
                public static final String NET_PROFILE_NO_EMULATION             = "No emulation";
                public static final String NET_PROFILE_4G_TYPICAL               = "4G typical";
                public static final String NET_PROFILE_4G_TYPICAL_INTL          = "4G typical - intercontinental";
                public static final String NET_PROFILE_4G_POOR                  = "4G poor";
                public static final String NET_PROFILE_4G_POOR_INTL             = "4G poor - intercontinental";
                public static final String NET_PROFILE_3G_TYPICAL               = "3G typical";
                public static final String NET_PROFILE_3G_TYPICAL_INTL          = "3G typical - intercontinental";
                public static final String NET_PROFILE_3G_POOR                  = "3G poor";
                public static final String NET_PROFILE_3G_POOR_INTL             = "3G poor - intercontinental";
                public static final String NET_PROFILE_2_5G_POOR                = "2.5G poor";
                public static final String NET_PROFILE_DISCONNECT               = "Network disconnection";
                
                public static void main(String[] args) {
                                
                                AndroidDriver<WebElement> driver = null;
                                
                                try {
                                                URL mcServerUrl = new URL("http://" + MC_SERVER_IP + ":8080/wd/hub");
                                                
                                                RequiredCapabilities capabilities = getBaseCapabilities();
                                                capabilities.setCapability("appPackage", "com.android.chrome");
                                                capabilities.setCapability("appActivity", "com.google.android.apps.chrome.Main");
                                                
                                                // Connect the driver to Mobile Center
                                                driver = new AndroidDriver<WebElement>(mcServerUrl, capabilities);
                                                
                                                // Install the NV Proxy certificate
                                                installCertificate(driver);
                                                
                                                // Configure proxy settings
                                                setWifiProxy(driver);
                                                
                                                // Make sure the same device is used on the next Appium run
                                                String deviceName = driver.getCapabilities().getCapability("deviceName").toString();
                                                
                                                // Quit the current Appium test
                                                driver.quit();
                                                
                                                // Connect and start the new Network Virtualization test
                                                capabilities = getBaseCapabilities();
                                                capabilities.setCapability("appPackage", "com.Advantage.aShopping");
                                                capabilities.setCapability("appActivity", "com.Advantage.aShopping.SplashActivity");
                                                capabilities.setCapability("udid", deviceName);
                                                
                                                // Select a network profile to use
                                                capabilities.setCapability("mc:net:profileName", NET_PROFILE_3G_POOR);
                                                driver = new AndroidDriver<WebElement>(mcServerUrl, capabilities);
                                                
                                                // ****************************************************************
                                                // ****************  Write your Appium test here  *****************
                                                // ****************************************************************

                                                // Clear the application cache
                                                driver.resetApp();
                                                
// Replace the content below with application-specific code
                                                runAdvantageAppScript(driver, "LAPTOPS");
                        
                        Object response= null;
                        
                        // Stop test and get NV Insights report
                        String fileName = "C:\\report.zip";
                        response = driver.executeScript("mc:net:getReport");
                        String base64Str = (String) response;
                        byte[] bytes = Base64.getDecoder().decode(base64Str);
                        IOUtils.write(bytes, new FileOutputStream(new File(fileName)));
                        
                        // get HAR file
                        fileName = "C:\\nv_har.zip";
                        response = driver.executeScript("mc:net:getHAR");
                        base64Str = (String) response;
                        bytes = Base64.getDecoder().decode(base64Str);
                        IOUtils.write(bytes, new FileOutputStream(new File(fileName)));
                        
                        // Clear proxy settings
                        clearWifiProxy(driver);
                        
                        // Remove proxy certificate
                        removeCertificate(driver);
                                }
                                catch (Exception e) {
                                                e.printStackTrace();
                                }
                                finally {
                                                if (driver != null) {
                                                                driver.quit();
                                                }
                                }
                }
                
                public static RequiredCapabilities getBaseCapabilities() {
                                RequiredCapabilities capabilities = new RequiredCapabilities();
                                capabilities.setCapability("userName", MC_SERVER_USER);
                                capabilities.setCapability("password", MC_SERVER_PASSWORD);
                                capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, Platform.ANDROID);
                                capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, ">=4.4.2");
                                return capabilities;
                }
                
                public static void installCertificate(AndroidDriver<WebElement> driver) {
                                Dimension screenDimention = driver.manage().window().getSize();
                                int screenHeight = screenDimention.getHeight();
                                int screenWidth = screenDimention.getWidth();
                                
                                waitForElementToShow(driver, 5, By.id("com.android.chrome:id/tab_switcher_button")).click();
                                
                                driver.findElement(By.id("com.android.chrome:id/new_tab_button")).click();
                                
                                waitForEitherElementToShow(driver, 6, new By[] 
                                                                {By.id("com.android.chrome:id/search_box_text"), By.id("com.android.chrome:id/url_bar")});
                                
                                if (isElementExist(driver, By.id("com.android.chrome:id/search_box_text"))) {
                                                driver.findElement(By.id("com.android.chrome:id/search_box_text")).click();
                                }
                                
                                WebElement urlBar = waitForElementToShow(driver, 10, By.id("com.android.chrome:id/url_bar"));
                                urlBar.sendKeys(CERT_URL);
                                driver.pressKeyCode(ENTER_KEY);
                                
                                boolean downloadBarExists = waitForEitherElementToShow(driver, 5, new By[] {
                                                                                                MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"Replace file\")"), 
                                                                                                By.id("com.android.chrome:id/snackbar_button"), 
                                                                                                By.id("com.android.chrome:id/infobar_message") });
                                
                                if (downloadBarExists) {
                                                if (isElementExist(driver, By.id("com.android.chrome:id/snackbar_button"))) {
                                                                driver.findElement(By.id("com.android.chrome:id/snackbar_button")).click();
                                                }
                                                else if (isElementExist(driver, 
                                                                                MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"Replace file\")")) || 
                                                                                isElementExist(driver, By.id("com.android.chrome:id/infobar_message"))) {
                                                                driver.findElement(By.id("com.android.chrome:id/button_primary")).click();
                                                                
                                                                clickElementIfExists(driver, By.id("com.android.chrome:id/snackbar_button"));
                                                }
                                }
                                
                                waitForEitherElementToShow(driver, 10, new By[] {
                                                                By.id("com.android.certinstaller:id/credential_name"), 
                                                                By.id("com.android.settings:id/password_entry") });
                                
                                if (isElementExist(driver, By.id("com.android.settings:id/password_entry"))) {
                                                driver.findElement(By.id("com.android.settings:id/password_entry")).sendKeys(DEVICE_PASSWORD);
                                                driver.pressKeyCode(ENTER_KEY);
                                }
                                
                                WebElement certNameElement = waitForElementToShow(driver, 10,
                                                                By.id("com.android.certinstaller:id/credential_name"));
                                certNameElement.clear();
                                certNameElement.sendKeys(CERT_NAME);
                                
                                waitForElementToShow(driver, 10, By.id("android:id/button1")).click();
                                
                                if (! isElementExist(driver, By.id("com.android.chrome:id/tab_switcher_button"))) {
                                                driver.navigate().back();
                                }
                                
                                WebElement switcherBtn = driver.findElement(By.id("com.android.chrome:id/tab_switcher_button"));
                                
                                String contentDesc = driver.findElement(By.id("com.android.chrome:id/tab_switcher_button"))
                                                                .getAttribute("name");
                                
                                switcherBtn.click();
                                
                                (new TouchAction(driver)).longPress(2, screenHeight-50)
                                                .moveTo(screenWidth-2, screenHeight-50).release().perform();
                                
                                if (Integer.parseInt(contentDesc.split(" ")[0]) > 1) {
                                                driver.navigate().back();
                                                
                                                sleep(500);
                                                driver.navigate().back();
                                }
                }
                
                public static void removeCertificate(AndroidDriver<WebElement> driver) {
                                driver.startActivity(new Activity("com.android.settings", ".Settings"));
                                
                                driver.findElement(By.id("com.android.settings:id/search")).click();
                                driver.findElement(By.id("android:id/search_src_text")).sendKeys("Trusted credentials");
                                driver.findElement(By.id("com.android.settings:id/title")).click();
                                scrollToElementByName(driver, "Trusted credentials").click();
                                
                                driver.findElement(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"User\")")).click();
                                
                                scrollToElementByName(driver, CERT_FULL_NAME).click();
                                scrollToElementByName(driver, "REMOVE");
                                
                                waitForEitherElementToShowAndReturnElement(driver, 5, new By[] {
                                                                By.id("com.android.settings:id/cert_remove_button"), 
                                                                By.id("android:id/button2") }).click();

                                driver.findElement(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"OK\")")).click();
                }
                
                public static void setWifiProxy(AndroidDriver<WebElement> driver) {
                                openNetworkProxySettings(driver);
                                
                                sleep(500);
                                
                                driver.findElementByAndroidUIAutomator(
                                                                "new UiSelector().textMatches(\"Manual\")").click();
                                
                                scrollToElementByName(driver, "port");
                                WebElement hostname = driver.findElement(By.id("com.android.settings:id/proxy_hostname"));
                                hostname.sendKeys(PROXY_IP);
                                
                                hideKeyboard(driver);
                                scrollToElementByName(driver, "port");
                                WebElement proxyPort = driver.findElement(By.id("com.android.settings:id/proxy_port"));
                                proxyPort.sendKeys(PROXY_PORT);
                                
                                driver.findElement(By.id("android:id/button1")).click();
                }
                
                public static void clearWifiProxy(AndroidDriver<WebElement> driver) {
                                openNetworkProxySettings(driver);
                                driver.findElement(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"None\")")).click();
                                driver.findElement(By.id("android:id/button1")).click();
                                driver.navigate().back();
                }
                
                public static void runAdvantageAppScript(AndroidDriver<WebElement> driver, String btnName) {                           
                                WebElement element = waitForElementToShow(driver, 15,
                                                                MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"" + btnName + "\")"));
                                element.click();
                                sleep(10000);
                                driver.navigate().back();
                }
                
                
                // Util functions
                private static void sleep(long millis){
                                try {
                                                Thread.sleep(millis);
                                }
                                catch (InterruptedException e) {
                                                e.printStackTrace();
                                }
                }
                
                public static void openNetworkProxySettings(AndroidDriver<WebElement> driver) {
                                driver.startActivity(new Activity("com.android.settings", "com.android.settings.wifi.WifiSettings"));
                                
                                waitForElementToShow(driver, 10, 
                                                                (MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"Connected\")")));
                                WebElement activeWifiWebElement = driver.findElement(
                                                                (MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"Connected\")")));
                                (new TouchAction(driver)).longPress(activeWifiWebElement, Duration.ofMillis(1200)).perform();
                                
                                driver.findElementByAndroidUIAutomator(
                                                                "new UiSelector().textMatches(\".*Modify network.*|Manage network settings\")").click();
                                
                                hideKeyboard(driver);
                                if (! isElementExist(driver, By.id("com.android.settings:id/proxy_settings"))) {
                                                driver.findElement(By.id("com.android.settings:id/wifi_advanced_togglebox")).click();
                                }
                                
                                scrollToElementByName(driver, "proxy");
                                hideKeyboard(driver);
                                
                                getElemntByIdFromPossibleList(driver, new String[] {
                                                                "com.android.settings:id/proxy_settings",
                                                                "com.android.settings:id/proxy_settings_fields" }).click();
                }

                public static WebElement getElementIfExist(AppiumDriver<WebElement> driver, By by) {
                                try {
                                                return driver.findElement(by);
                                }
                                catch (NoSuchElementException e) {
                                                return null;
                                }
                }
                
                public static boolean isElementExist(AppiumDriver<WebElement> driver, By by) {
                                return (getElementIfExist(driver, by) != null);
                }
                
                public static void clickElementIfExists(AppiumDriver<WebElement> driver, By by) {
                                WebElement element = getElementIfExist(driver, by);
                                if (element != null) {
                                                element.click();
                                }
                }
                
                public static WebElement waitForElementToShow(AppiumDriver<WebElement> driver, 
                                                long timeOutInSeconds, By by) {
                                WebDriverWait webDriverWait = new WebDriverWait(driver, timeOutInSeconds);
                                return webDriverWait.until(ExpectedConditions.visibilityOfElementLocated (by));
                }
                
                public static boolean waitForEitherElementToShow(AndroidDriver<WebElement> driver, 
                                                long timeInSeconds, By[] bys) {
                                for (int i = 0; i < timeInSeconds*2; i++) {
                                                for (By by: bys) {
                                                                if (isElementExist(driver, by)) return true;
                                                }
                                                sleep(500);
                                }
                                
                                return false;
                }
                
                public static WebElement waitForEitherElementToShowAndReturnElement(AndroidDriver<WebElement> driver, 
                                                long timeInSeconds, By[] bys) {
                                for (int i = 0; i < timeInSeconds*2; i++) {
                                                for (By by: bys) {
                                                                if (isElementExist(driver, by)) 
                                                                                return driver.findElement(by);
                                                }
                                                sleep(500);
                                }
                                
                                return null;
                }
                
                public static WebElement scrollToElementByName(AndroidDriver<WebElement> driver, String elementName) {
                                String str = "new UiScrollable(new UiSelector().scrollable(true).instance(0))."
                                                                + "scrollIntoView(new UiSelector().textContains(\""+elementName+"\").instance(0))";
                                return driver.findElementByAndroidUIAutomator(str);
                }
                
                public static void hideKeyboard(AndroidDriver<WebElement> driver) {
                                try {
                                                driver.hideKeyboard();
                                }
                                catch (WebDriverException e) {}
                }
                
                public static WebElement getElemntByIdFromPossibleList(
                                                AndroidDriver<WebElement> driver, String[] possibleIDs) {
                                NoSuchElementException nsee = null;
                                
                                for (String id : possibleIDs) {
                                                try {
                                                                WebElement element = driver.findElement(By.id(id));
                                                                return element;
                                                }
                                                catch (NoSuchElementException e) {
                                                                nsee = e;
                                                }
                                }
                                throw nsee;
                }
}

Back to top

See also: