Upload
vukhanh
View
231
Download
0
Embed Size (px)
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/
[email protected]@gogoair.com