Mobile Apps Test automation challenges at Gogo · Prerequisites for Automation framework §...

Preview:

Citation preview

Mobile Apps Test automation challenges at Gogo

June 26, 2017 • Room #404

Vinay Kumar & Anu Sahithi – GOGO

ABOUT GOGO:

July 10, 2017 2

• We are the leading global provider of connectivity products and services for aviation. Gogo has more than 3000 commercial aircraft equipped and 4,200 business broadband connected on our networks.

• We have 17 major airline partners and have had more than 120 million sessions on our network since we launched our commercial service

• We also have the leading share of the business aviation market as well

July 10, 2017 3

July 10, 2017 4

QE Automation Work Flow

July 10, 2017 5

Prerequisites for Automation framework§ Selenium WebDriver with Java.§ Selenium GRID§ Appium – iOS and Android.§ TestNG, Report generation, Batch execution§ Gitlab and Gradle§ Data Driven Framework –JSON,Property files,XMLs§ Continuous Integration – Jenkins AWS Cloud§ Cucumber JVM - BDD Framework§ Rest Assured – Web services.

Host Machines Connecting to Network

Gradle – build.gradle vs Maven-POM.xml

§ dependencies {§ testCompile "org.seleniumhq.selenium:selenium-java:2.53.1"§ testCompile 'org.testng:testng:6.9.4'§ testCompile "io.appium:java-client:3.2.0"§ testCompile 'com.relevantcodes:extentreports:2.031'§ testCompile 'org.jsoup:jsoup:1.7.2'§ testCompile 'com.jayway.restassured:rest-assured:2.7.0'§ testCompile 'com.googlecode.json-simple:json-simple:1.1'§ testCompile 'com.jcraft:jsch:0.1.44-1'§ testCompile 'log4j:log4j:1.2.17'§ testCompile 'mysql:mysql-connector-java:5.1.6'§ } § clean.doFirst {§ delete "${rootDir}/Reports/HTMLReports/"§ println "${rootDir}/Reports/HTMLReports/"§ delete "${rootDir}/src/logs/"§ println "${rootDir}/src/logs/"}

§ test {§ systemProperty 'airlineEnvironment', "$airlineEnvironment"§ systemProperty 'testEnvironment', "$testEnvironment"§ systemProperty 'testSetup', "$testSetup"§ systemProperty 'level', "$level"§ useTestNG(){§ suites file('testng.xml')§ useDefaultListeners()§ configFailurePolicy="continue"§ listeners << 'org.testng.reporters.EmailableReporter'§ includeGroups System.getProperty('level')§ }§ }

Mobile automation challenges in GOGO § Multiple devices to support.

§ Work on both IOS and Android.

§ Connecting the mobile devices to SSID.

§ Stable browser driver session.

§ Native App player integration.

July 10, 2017 8

Why not simulators?§ Doesn’t simulate the exact functionality as in Devices.

§ Difficult to find any performance related issues.

§ Unable to test captive browser scenarios.

§ Unable to test on Multiple Device Scenarios.

§ Multiple flavors of OS versions.

July 10, 2017 9

Demonstration of Mobile Automation

Host Machines Connecting to Network

Host Connecting to Network (Windows)

§ if(pla1.equalsIgnoreCase("windows") || pla1.equalsIgnoreCase("Android")){§ String userDir = System.getProperty("user.dir");§ String exportProfile = "cmd /K start netsh wlan export profile name=\"" + ssid1 + "\" folder=\""+userDir+"\\Profile\"";

§ Runtime.getRuntime().exec(exportProfile);§ File exportProfileFile = new File (userDir+"\\Profile\\Wi-Fi-" + ssid1 + ".xml");§ if(!exportProfileFile.exists() && !ssid1.equals("gogo")) {§ infoLog("Profile doesn't exist");

§ //Create Profile§ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(§ new InputSource(userDir+"\\Profile\\Wi-Fi-Template.xml"));§ String profile = convertDocumentToString(doc);

§ profile = profile.replaceAll("TEST", ssid1);§ doc = convertStringToDocument(profile);§ Transformer xformer = TransformerFactory.newInstance().newTransformer();§ xformer.transform(new DOMSource(doc), new StreamResult(new File(userDir+"\\Profile\\Wi-Fi-" + ssid1 + ".xml")));§ //Import Profile§ String importProfile = "cmd /K start netsh wlan add profile filename=\""+userDir+"\\Profile\\Wi-Fi-" + ssid1 + ".xml\"

user=all interface=w*";

§ Runtime.getRuntime().exec(importProfile);§ Thread.sleep(3000);§ }§ //Connect to SSID

§ try { § Thread.sleep(1000);§ String connectToWinWifi="cmd /K start netsh wlan connect name=\""+ssid1+"\"";§ Runtime.getRuntime().exec(connectToWinWifi);

§ Thread.sleep(5000);§ } § catch (IOException ex) {infoLog("Unable to connect to Wifi");}§ currentSSID = Runtime.getRuntime().exec("netsh wlan show interfaces"); § Runtime.getRuntime().exec("cmd /K del "+userDir+"\\Profile\\Wi-Fi-" + ssid1 + ".xml");

§ }§ }

Host Machines Connecting to Network

Host Connecting to Network (MAC)

§ else if(System.getProperty("os.name").contains("Mac")){§ if(pla1.equalsIgnoreCase("Mac") ||pla1.equalsIgnoreCase("ios")){§ //Connect to SSID

§ currentSSID = Runtime.getRuntime().exec("/System/Library/PrivateFrameworks/Apple80211.framework/versions/A/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'");

§ if(!ssid1.equals("gogo")){§ try{ § String ConnectToMacWifi = "networksetup -setairportnetwork en0 "+ssid1;§ Runtime.getRuntime().exec(ConnectToMacWifi);§ Thread.sleep(4000);

§ // String verifyconn = "/System/Library/PrivateFrameworks/Apple80211.framework/versions/A/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'";

§ currentSSID = Runtime.getRuntime().exec("/System/Library/PrivateFrameworks/Apple80211.framework/versions/A/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}')");

§ }§ catch(IOException ex1){infoLog("Unable to connect to Mac Wifi");}§ }§ }§ }§ //Check if connected to SSID

§ String response = runProcessString(currentSSID);§ if(response.contains(ssid1))§ connectedToSSID = true;§ count++;

§ if(count == 3){§ failLog("Could not connect to SSID " +ssid1);§ }§ }

§ //If unable to connect to SSID skip test§ if((connectedToSSID == false) && (count >= 3)){§ throw new SkipException("Skipping this exception, couldn't connect to " + ssid1 + ".");§ }

§ infoLog("Connected to " + ssid1);§ }

Mobile Devices Connecting to Network

Creating Node JSON

§ public void createSettingsJSON(String UDID,String deviceSettingType) throws Exception{§ JSONObject obj = new JSONObject();§ JSONObject obj1 = new JSONObject();§ JSONObject obj2 = new JSONObject();§ JSONArray list = new JSONArray();§ obj1.put("browserName","");

§ obj1.put("platformversion","Settings"+UDID);§ obj1.put("maxInstances", new Integer(2));§ obj1.put("platformName", "Android");

§ obj1.put("deviceName", "Nexus");

§ obj1.put("platform","ANDROID");§ obj1.put("version","Settings"+UDID);

§ if(deviceSettingType.equals("GridSettings")){§ obj1.put("appActivity", "com.android.settings.GridSettings");§ obj1.put("appActivity", "com.android.settings.SettingsTabActivity");

§ }

§ else if(deviceSettingType.equals("Settings")){§ obj1.put("appPackage","com.android.settings");

§ obj1.put("appActivity","com.android.settings.Settings");

§ }§ obj2.put("nodeTimeout",120);

§ obj2.put("port",4728);

§ obj2.put("hubPort",4444);§ obj2.put("proxy", "org.openqa.grid.selenium.proxy.DefaultRemoteProxy");

§ obj2.put("url","http://127.0.0.1:4728");

§ obj2.put("hub","http://localhost:4444/grid/register");§ obj2.put("hubHost","localhost");

§ obj2.put("nodePolling",2000);

§ obj2.put("registerCycle",10000);§ obj2.put("register",true);§ obj2.put("cleanUpCycle",2000);

§ obj2.put("timeout",30000);§ obj2.put("maxSession",2);

§ obj2.put("host","127.0.0.1");

§ list.add(obj1);

§ obj.put("capabilities", list);§ obj.put("configuration", obj2);

§ try {§ FileWriter file = new FileWriter(System.getProperty("user.dir")+"/src/test/Settings"+UDID+".json");§ file.write(obj.toJSONString().replaceAll("\\\\/", "/"));

§ file.flush();

§ file.close();§ } catch (IOException e) {§ e.printStackTrace();

§ }

§ }

Mobile Devices Connecting to Network

Devices connecting to Network

§ Process checkRoot = Runtime.getRuntime().exec("adb root");§ String rootString = runProcessString(checkRoot);

§ if(rootString.contains("cannot run as root")){§ infoLog("Error: Device not rooted.");§ root = false;§ }

§ else§ root = true;§ if((root == true) && (proxySetter == true)){§ if(envrSetup.contains("LRU")){§ //should already be connected§ }

§ else{§ Thread.sleep(15000);§ Runtime.getRuntime().exec("adb shell svc wifi disable");

§ Thread.sleep(2000);

§

§ //Pull wpa_supplicant.conf

§ Process pullConfig = Runtime.getRuntime().exec("adb pull /data/misc/wifi/wpa_supplicant.conf "+downloadPath+"\\wpa_supplicant.conf");

§ String processPullConfig = runProcessString(pullConfig);§ infoLog("-"+processPullConfig+"-");

§

§ //Edit .conf§ @SuppressWarnings("resource")

§ String confContent = new Scanner(new File(downloadPath+"\\wpa_supplicant.conf")).useDelimiter("\\Z").next();§ String gogoNetwork = "\n\nnetwork={\n\tssid=\"gogo\"\n\tkey_mgmt=WPA-EAP IEEE8021X\n\teap=PEAP\n\tidentity=\"itqa\"" +§ "\n\tpassword=\"Password!\"\n\tphase2=\"auth=MSCHAPV2\"\n\tpriority=1\n\tproactive_key_caching=1\n}";

§ String confComplete = confContent + gogoNetwork;

§ // infoLog(confComplete);§ PrintWriter out = new PrintWriter(downloadPath+"\\wpa_supplicant.conf");§ out.println(confComplete);

§ out.close(); § //Push .conf

§ Process pushConfig = Runtime.getRuntime().exec("adb push "+downloadPath+"\\wpa_supplicant.conf /data/misc/wifi/wpa_supplicant.conf");

§ String processPushConfig = runProcessString(pushConfig);

§ infoLog(""+processPushConfig);§ Thread.sleep(1000);

§ //Enable wifi open settings

§ Runtime.getRuntime().exec("adb shell chown system.wifi /data/misc/wifi/wpa_supplicant.conf");§ Runtime.getRuntime().exec("adb shell chmod 660 /data/misc/wifi/wpa_supplicant.conf");

§ Runtime.getRuntime().exec("adb shell svc wifi enable");

§ //Connect to Gogo

§ Process gogoConnect = Runtime.getRuntime().exec("adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e clear true");§ String processGogoConnect = runProcessString(gogoConnect);§ infoLog(""+processGogoConnect);

§

Mobile Devices Connecting to Network

Devices connecting to Network (Continued)

§ AppiumDriver driverForSettings;

§ String Proxy="Mobile_ProxyName_"+airlineEnvr1;

§ String ProxyName=CONFIG.getProperty(Proxy);

§ // String deviceType = "tablet";§ String deviceSettingType = deviceSettingsType(udid);

§ infoLog("deviceSettingsType: "+deviceSettingsType(udid));

§ createSettingsJSON(udid,deviceSettingType);

§ try{§ if(System.getProperty("os.name").contains("Windows")){ § Thread.sleep(8000);

§ String path = System.getProperty("user.dir")+"/src/test/Settings"+udid+".json";

§ Runtime.getRuntime().exec("cmd /K start node.exe appium.js -a 127.0.0.1 -p 4728 --bootstrap-port 4729 -U "+udid+" --no-reset --nodeconfig "+path,null,new File("C:\\Program Files (x86)\\Appium\\node_modules\\appium\\bin"));

§ Thread.sleep(18000);

§

§ }

§ if(System.getProperty("os.name").contains("Mac")){ § Thread.sleep(8000);

§ String path= System.getProperty("user.dir")+"/src/test/Settings"+udid+".json";

§ Runtime.getRuntime().exec("node /usr/local/lib/node_modules/appium/bin/appium.js -a 127.0.0.1 -p 4728 --bootstrap-port 4729 -U "+udid+" --no-reset --nodeconfig"+path,null,newFile("/usr/local/bin"));

§ Thread.sleep(12000);

§ } }catch(IOException ex1){}§ DesiredCapabilities caps = new DesiredCapabilities();§ caps.setCapability(CapabilityType.BROWSER_NAME, "");§ caps.setCapability("deviceName", "Nexus");

§ caps.setCapability("platformversion", "Settings"+udid);

§ caps.setCapability("platformName", "Android");

Managing Multiple Driver sessions(Settings)

Managing Multiple Driver sessions (Windows & Android)

Managing Multiple Driver sessions(MAC & IOS)

DevOps and Quality Engineering Pipeline

July 10, 2017 19

Gitlab DEVRepo

CreateRPM/isoimageJenkinsCIDSL.groovy

Bake DeploysonDEV

DeploysonSTAGE

DeploysonPROD

Runway/Pipeline.json

Gitlab DEVRepo

Gitlab QERepo

JenkinsQEDSL.groovy

DEVJenkinsFlow

SpinnakerBuildPipeline

QEJenkinsFlow

FailFail Fail

Results Results Results

QE-DevPass QE-StagePass

Airlineleveloftest,test.environment

1. 2. 3.

4. 5. 7. 8. 10. 11.

6. 9.

Test Result Reporting in Jenkins

Test Execution Reports

July 10, 2017 22

THANK YOU!

July 10, 2017 23

Vinay Kumar & Anu Sahithi

Social

in/vinay-kumar-64851822

https://www.linkedin.com/in/anusahithi-tammineni-

71782b71/

EmailVBhojaraja@gogoair.comAtammineni@gogoair.com

Recommended