iOS and Android Apps automation By, Sridhar Ramakrishnan Life long travel geek @ Hotwire Inc.
Agenda • How is Native app testing is different from Web testing • Kind of Native app bugs • Test automation • Different framework for native apps automation • What is appium & how it works • Android & iOS frameworks – Espresso & Xcode UI testing • Sample test code • Demo • Code Coverage • Our CI process • Screenshot testing – Image comparison tests • Tracking • So why we are doing all this??
How is Native app testing is different from Web testing • Usability & interaction • Faster & more reactive • Involves Gestures • No unnecessary content • Data Entry Keyboard Types • Numeric vs. Alphanumeric • Phone Settings • Changing Regions • Changing Location Services • Changing Notifications • Devices vs. Simulators • Multiple Devices and Operating Systems
Bugs Types • Crashes • Missing data from the API • Missing data in the app • Wrong keyboard displayed • Rendering differences across devices • Views overlaying one another • Views are getting locked up • Gesture related – swipe, double tap
More Bugs ? • Limited manual regression testing = Spot check ; less boring • More manual exploratory testing = More bugs; “Simultaneously learning about the system while designing and executing tests, using feedback from the last test to inform the next.” - Elisabeth Hendrickson
Test Automation
Frameworks comparison Frameworks for comparison Test the actual app Many language Standard API ( Webdriver) Open source & active BDD iOS Android Hybrid Firefox OS Appium Xcode UI Automation calabash-iOS Frank ios-driver KIF Robotium Espresso selendroid
Test Automation @ Hotwire • Test Framework = Hotwire BDD • Tools = Xcode UI testing • API = Spoofer (mock) vs API calls
Appium – Multi OS Support And More…
Appium Architecture Test Script ( Java ) Webdriver (Seleium Java) Apple Instruments (Instruments.js) iPhone / iPad [Simulator / Device] APP Android [Simulator / Device] APP Android (adb, UIAutomator (AppiumBootstr ap.jar …) FireFox OS / Hybrid Apps Firefox OS / Web browser BDD (Cucumber, Webdriver, Spring, maven) CI – Jenkins (Build xcode, start Appium server, mvn install Appium server (Node.js) JSJSON
BDD – Cucumber & Gherkin Feature: Hotel Search and Book Scenario: Search and book hotel as Sign In user Given I'm searching for hotel and attempt to book When I book a hotel as valid signed in user Then I should see confirmation that my hotel is booked
BDD – Cucumber @tags @iOS @Android @SMOKE Feature: Hotel Search and Book Scenario: Search and book hotel as Sign In user Given I'm searching for hotel and attempt to book When I book a hotel as valid signed in user Then I should see confirmation that my hotel is booked
BDD – StepDefs //Spring context file @ContextConfiguration("classpath:cucumber.xml") //hotel object gets input from Spring @Autowired private Hotel hotel; @Given("^I'm searching for hotel and attempt to book$") public void search() { hotel.search(); }
Java code public interface Hotel { void search(); } // iOS public class IosHotelImpl implements Hotel { @Override Public void search() { IosSearchScreen iosSearchScreenObj = new IosSearchScreen(getWebDriver()); } // Android public class AndroidHotelImpl implements Hotel { @Override Public void search() { AndroidSearchScreen androidSearchScreenObj = new AndroidSearchScreen(getWebDriver()); }
Screen Objects - iOS // iOS Screen Object public class iOSSearchScreen extends AbstractScreen { @FindBy(name = ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
Screen Objects - Android // Android Screen object public class AndroidSearchScreen extends AbstractScreen { @FindBy(id= ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
Screen Objects public class AbstractScreen { private final WebDriver webdriver; public AbstractScreen(WebDriver webdriver) { PageFactory.initElements(webdriver, this); this.webdriver = webdriver; } protected WebDriver getWebDriver() { return webdriver; } }
BDD – StepDefs //Spring context file @ContextConfiguration("classpath:cucumber.xml") //hotel object assigned by Spring @Autowired private Hotel hotel; @Given("^I'm searching for hotel and attempt to book$") public void search() { hotel.search(); }
Dependency Injection using Spring Framework Context file - Cucumber.xml <context:component-scan base-package="com.test" /> <import resource="cucumber-${mobileOS}.xml"/>
Dependency Injection using Spring Framework Cucumber-ios.xml <bean id="hotel" class="com.test.ios.hotel.IosHotelImpl"> </bean> <bean id="desiredCapabilities" class="org.openqa.selenium.remote.DesiredCapabilities">
Dependency Injection using Spring Framework Cucumber-android.xml <bean id="hotel" class="com.test.android.hotel.AndroidHotelImpl"> </bean> <bean id="desiredCapabilities" class="org.openqa.selenium.remote.DesiredCapabilities">
Managing Dependency 3rd Party Jars Cucumber Spring Reporting Junit / testng … Tests Jars Features StepDefs iOS-Screen-Objects Android-Screen-Objects …
Hotwire Apps BDD architecture Screen Objects (Objects representing screen / fragment) Appium server (Node.js) Apple Instruments with UI Automation iPhone / iPad [Simulator / Device] APP JSON JS
Appium locator & tools WebDriver Locators : • ID • Name • Xpath Tools : • Appium inspector (iOS) • Uiautomatorviewer (Android)
Appium Sample Code – Send Text and Tap @FindBy(name = "Email address") private WebElement emailAddress; @FindBy(name = "Password") private WebElement password; @FindBy(name = "Sign in") private WebElement signIn; public void enterSignIn(String emailAddress, String password) { this.emailAddress.clear(); this.emailAddress.sendKeys(emailAddress); this.password.clear(); this.password.sendKeys(password); this.signIn.click(); }
Sample Code – Swipe functionality private void swipeFunctionality(WebElement startPoint, WebElement endPoint) { HashMap<String, Double> args = new HashMap<>(); double x1 = startPoint.getLocation().getX(); double y1 = startPoint.getLocation().getY(); double width1 = startPoint.getSize().getWidth(); double height1 = startPoint.getSize().getHeight(); args.put("touchCount", (double) 1); args.put("startX", (double) (x1 + width1) - 5); args.put("startY", (double) (y1 + height1 / 2)); double x2 = endPoint.getLocation().getX(); double y2 = endPoint.getLocation().getY(); double width2 = endPoint.getSize().getWidth(); double height2 = endPoint.getSize().getHeight(); args.put("touchCount", (double) 1); args.put("endX", (double) (x2 + width2) - 5); args.put("endY", (double) (y2 + height2 / 2)); args.put("duration", (double) 1); executeScript("mobile: swipe", args); } public Object executeScript(String script, Object... args) { return ((JavascriptExecutor) getAppiumDriver()).executeScript(script, args); }
Sample code (contd.) if (checkInDate.equals(LocalDate.now().plusDays(1))) { LocalDate currentDate = LocalDate.now(); String currentMonth = new SimpleDateFormat("MMMM").format(currentDate.toDateTimeAtStartOfDay().toDate()); String currentDay = currentDate.dayOfMonth().getAsString(); String currentWeekName = currentDate.withDayOfWeek(currentDate.getDayOfWeek()).dayOfWeek().getAsText(); String currentCheckin = "S_Today, " + currentWeekName + ", " + currentMonth + " " + currentDay; WebElement currentElmt = getAppiumDriver().findElement(By.name(currentCheckin)); swipeFunctionality(currentElmt, checkOutElmt); } else if (checkInMonth.equals(checkOutMonth) || nextToCheckInMonth.equalsIgnoreCase(checkOutMonth)) { checkInElmt.click(); if (tapOrDrag.equalsIgnoreCase("tap")) { checkOutElmt.click(); } else if (tapOrDrag.equalsIgnoreCase("tap and drag")) { swipeFunctionality(checkInElmt, checkOutElmt); } else { swipeFunctionality(nextToCheckInElmt, checkOutElmt); } } else { checkInElmt.click(); if (tapOrDrag.equalsIgnoreCase("tap")) { fillCalendarMonth(checkOutMonth); checkOutElmt.click(); } else if (tapOrDrag.equalsIgnoreCase("tap and drag")) { WebElement middleElmt = findMiddleElement(checkInDate, checkInDay, checkInMonth); swipeFunctionality(checkInElmt, middleElmt); fillCalendarMonth(checkOutMonth); swipeFunctionality(middleElmt, checkOutElmt); } else { WebElement middleElmt = findMiddleElement(checkInDate, checkInDay, checkInMonth); swipeFunctionality(nextToCheckInElmt, middleElmt); fillCalendarMonth(checkOutMonth); swipeFunctionality(middleElmt, checkOutElmt); } }
iOS Demo
Native frameworks • Espresso – Android • Xcode UI testing - iOS
Espresso • Espresso is an open source Android test automation framework from Google. • Espresso is API for UI Testing on Android. • Espresso core API is small, predictable and easy to learn. • Espresso is a thin layer on top of Android Instrumentation that makes it easy to write reliable UI tests. • It supports all Android versions. • Tests run optimally fast as there is no need for any sleeps (tests run on same millisecond when the app becomes idle)
Espresso: Code Example public class EspressoTest extends ActivityInstrumentationTestCase2<HomeScreenActivity> { public EspressoTest() { super(HomeScreenActivity.class); } @Override public void setUp() throws Exception { super.setUp(); getActivity(); } @Test public void testSearchHotel() { //finding a view with onView and perfoming an action onView(withId(com.hotwire.hotels.R.id.current_location_edittext)) .perform(click()); onView(withId(com.hotwire.hotels.R.id.destination)).perform(typeText("San Francison")); onView(withId(com.hotwire.hotels.R.id.search_hotels_button)).perform(click()); } }
Android Demo
Xcode UI testing • Available from Xcode 7 • New feature added to XCTest framework • UI recording • Ease to locate elements • Run tests on multiple iOS versions • Integrates with Xcode server • Code coverage
But why? We already have Appium - Faster execution time (1m45sec vs 5m45sec) - Faster to write too (Record feature) - No Appium/3rd party dependencies - Free code coverage reports - Handles wait times implicitly - Snapshot of failed tests - Consolidated reports
UI testing : Code Example import XCTest class HotwireUITests: XCTestCase { override func setUp() { super.setUp() continueAfterFailure = false XCUIApplication().launch() } func testIPadHotel() { //HomeScreen verification let homeScreen = HomeScreen() homeScreen.verifyHomeScreenElements() //Hotel Search with Signed In User homeScreen.navigateToHotel() //Hotel Farefinder verification let hotelFF = HotelFareFinder() hotelFF.verifyFareFinderElements() hotelFF.findHotel() } import Foundation import XCTest class CarBookingScreen { let elementsQuery = XCUIApplication().scrollViews.otherElements let toolbarsQuery = XCUIApplication().toolbars func goToSignIn(){ elementsQuery.buttons["SIGN IN"].tap() } func completeBooking(){ enterCCV() elementsQuery.switches["AgeRestriction"].tap() elementsQuery.buttons["Book Now"].tap() } }
Xcode UI testing for iPad : Demo
Code coverage - iOS • Tool : LCOV - Collects data from multiple source files , creates HTML pages containing source code annotated with coverage • GitHub - XCodeCoverage - Instrument classes - Run tests - Generate reports(./getcov)
Code coverage - iOS
public class Main { private String s; public static void main(String[] args){ //some code goes here if (something != null) { //body } } } public class Main { private String s; //magic infused public static void main(String[] args){ //report that method was executed //some code goes here if (something != null) { //report that condition was met //body } } } Original class Instrumented class Code coverage – Android using Emma
iOS / Android CI Goal To provide rapid feedback so that if a bug is introduced into the code base, it can be identified and fixed as soon as possible. Jenkins We are using Jenkins for all our CI runs at the moment, triggered on each Git check-in iOS / Android CI Pipelines • Master Pipeline • Develop Pipeline • Release Pipeline • Feature Pipeline Polling Nodes/hosts from an iOS and Android host-cluster, polled for each leg of the pipeline execution. Artifacts are zipped and transferred between jobs. • Less wait time for resources • Parallel job execution
iOS CI Build * Unit Tests * iPad Smoke Car/Hotel, iPhone Smoke Car/Hotel * Regression
iOS CI • Reporting & Snapshots
iOS CI
Screenshot testing • Image comparison – Screen by screen. Why ? – Saves time testing UI layout on various sized screens – New UI bugs caught faster – Helps reduce Regression Cycle Time • ImageMagick tool
CI – Screenshot comparison
Analytics automation • Log analytics / tracking information • Read Appium log file • Assert for expected values
So why are we doing all this? • Feedback loop – faster @ story level • Regression – 0.5 to 1 day from 5 days • Speed with quality • Visibility
Hotwire automation framework • To be Open sourced soon. Watch out -> https://github.com/HotwireDotCom/
Questions ?

iOS and Android apps automation

  • 1.
    iOS and AndroidApps automation By, Sridhar Ramakrishnan Life long travel geek @ Hotwire Inc.
  • 2.
    Agenda • How isNative app testing is different from Web testing • Kind of Native app bugs • Test automation • Different framework for native apps automation • What is appium & how it works • Android & iOS frameworks – Espresso & Xcode UI testing • Sample test code • Demo • Code Coverage • Our CI process • Screenshot testing – Image comparison tests • Tracking • So why we are doing all this??
  • 3.
    How is Nativeapp testing is different from Web testing • Usability & interaction • Faster & more reactive • Involves Gestures • No unnecessary content • Data Entry Keyboard Types • Numeric vs. Alphanumeric • Phone Settings • Changing Regions • Changing Location Services • Changing Notifications • Devices vs. Simulators • Multiple Devices and Operating Systems
  • 4.
    Bugs Types • Crashes •Missing data from the API • Missing data in the app • Wrong keyboard displayed • Rendering differences across devices • Views overlaying one another • Views are getting locked up • Gesture related – swipe, double tap
  • 5.
    More Bugs ? •Limited manual regression testing = Spot check ; less boring • More manual exploratory testing = More bugs; “Simultaneously learning about the system while designing and executing tests, using feedback from the last test to inform the next.” - Elisabeth Hendrickson
  • 6.
  • 7.
    Frameworks comparison Frameworks for comparison Testthe actual app Many language Standard API ( Webdriver) Open source & active BDD iOS Android Hybrid Firefox OS Appium Xcode UI Automation calabash-iOS Frank ios-driver KIF Robotium Espresso selendroid
  • 8.
    Test Automation @Hotwire • Test Framework = Hotwire BDD • Tools = Xcode UI testing • API = Spoofer (mock) vs API calls
  • 9.
    Appium – MultiOS Support And More…
  • 10.
    Appium Architecture Test Script( Java ) Webdriver (Seleium Java) Apple Instruments (Instruments.js) iPhone / iPad [Simulator / Device] APP Android [Simulator / Device] APP Android (adb, UIAutomator (AppiumBootstr ap.jar …) FireFox OS / Hybrid Apps Firefox OS / Web browser BDD (Cucumber, Webdriver, Spring, maven) CI – Jenkins (Build xcode, start Appium server, mvn install Appium server (Node.js) JSJSON
  • 11.
    BDD – Cucumber& Gherkin Feature: Hotel Search and Book Scenario: Search and book hotel as Sign In user Given I'm searching for hotel and attempt to book When I book a hotel as valid signed in user Then I should see confirmation that my hotel is booked
  • 12.
    BDD – Cucumber@tags @iOS @Android @SMOKE Feature: Hotel Search and Book Scenario: Search and book hotel as Sign In user Given I'm searching for hotel and attempt to book When I book a hotel as valid signed in user Then I should see confirmation that my hotel is booked
  • 13.
    BDD – StepDefs //Springcontext file @ContextConfiguration("classpath:cucumber.xml") //hotel object gets input from Spring @Autowired private Hotel hotel; @Given("^I'm searching for hotel and attempt to book$") public void search() { hotel.search(); }
  • 14.
    Java code public interface Hotel{ void search(); } // iOS public class IosHotelImpl implements Hotel { @Override Public void search() { IosSearchScreen iosSearchScreenObj = new IosSearchScreen(getWebDriver()); } // Android public class AndroidHotelImpl implements Hotel { @Override Public void search() { AndroidSearchScreen androidSearchScreenObj = new AndroidSearchScreen(getWebDriver()); }
  • 15.
    Screen Objects -iOS // iOS Screen Object public class iOSSearchScreen extends AbstractScreen { @FindBy(name = ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
  • 16.
    Screen Objects -Android // Android Screen object public class AndroidSearchScreen extends AbstractScreen { @FindBy(id= ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
  • 17.
    Screen Objects public classAbstractScreen { private final WebDriver webdriver; public AbstractScreen(WebDriver webdriver) { PageFactory.initElements(webdriver, this); this.webdriver = webdriver; } protected WebDriver getWebDriver() { return webdriver; } }
  • 18.
    BDD – StepDefs //Springcontext file @ContextConfiguration("classpath:cucumber.xml") //hotel object assigned by Spring @Autowired private Hotel hotel; @Given("^I'm searching for hotel and attempt to book$") public void search() { hotel.search(); }
  • 19.
    Dependency Injection using SpringFramework Context file - Cucumber.xml <context:component-scan base-package="com.test" /> <import resource="cucumber-${mobileOS}.xml"/>
  • 20.
    Dependency Injection using SpringFramework Cucumber-ios.xml <bean id="hotel" class="com.test.ios.hotel.IosHotelImpl"> </bean> <bean id="desiredCapabilities" class="org.openqa.selenium.remote.DesiredCapabilities">
  • 21.
    Dependency Injection using SpringFramework Cucumber-android.xml <bean id="hotel" class="com.test.android.hotel.AndroidHotelImpl"> </bean> <bean id="desiredCapabilities" class="org.openqa.selenium.remote.DesiredCapabilities">
  • 22.
    Managing Dependency 3rd PartyJars Cucumber Spring Reporting Junit / testng … Tests Jars Features StepDefs iOS-Screen-Objects Android-Screen-Objects …
  • 23.
    Hotwire Apps BDDarchitecture Screen Objects (Objects representing screen / fragment) Appium server (Node.js) Apple Instruments with UI Automation iPhone / iPad [Simulator / Device] APP JSON JS
  • 24.
    Appium locator &tools WebDriver Locators : • ID • Name • Xpath Tools : • Appium inspector (iOS) • Uiautomatorviewer (Android)
  • 25.
    Appium Sample Code– Send Text and Tap @FindBy(name = "Email address") private WebElement emailAddress; @FindBy(name = "Password") private WebElement password; @FindBy(name = "Sign in") private WebElement signIn; public void enterSignIn(String emailAddress, String password) { this.emailAddress.clear(); this.emailAddress.sendKeys(emailAddress); this.password.clear(); this.password.sendKeys(password); this.signIn.click(); }
  • 26.
    Sample Code –Swipe functionality private void swipeFunctionality(WebElement startPoint, WebElement endPoint) { HashMap<String, Double> args = new HashMap<>(); double x1 = startPoint.getLocation().getX(); double y1 = startPoint.getLocation().getY(); double width1 = startPoint.getSize().getWidth(); double height1 = startPoint.getSize().getHeight(); args.put("touchCount", (double) 1); args.put("startX", (double) (x1 + width1) - 5); args.put("startY", (double) (y1 + height1 / 2)); double x2 = endPoint.getLocation().getX(); double y2 = endPoint.getLocation().getY(); double width2 = endPoint.getSize().getWidth(); double height2 = endPoint.getSize().getHeight(); args.put("touchCount", (double) 1); args.put("endX", (double) (x2 + width2) - 5); args.put("endY", (double) (y2 + height2 / 2)); args.put("duration", (double) 1); executeScript("mobile: swipe", args); } public Object executeScript(String script, Object... args) { return ((JavascriptExecutor) getAppiumDriver()).executeScript(script, args); }
  • 28.
    Sample code (contd.) if(checkInDate.equals(LocalDate.now().plusDays(1))) { LocalDate currentDate = LocalDate.now(); String currentMonth = new SimpleDateFormat("MMMM").format(currentDate.toDateTimeAtStartOfDay().toDate()); String currentDay = currentDate.dayOfMonth().getAsString(); String currentWeekName = currentDate.withDayOfWeek(currentDate.getDayOfWeek()).dayOfWeek().getAsText(); String currentCheckin = "S_Today, " + currentWeekName + ", " + currentMonth + " " + currentDay; WebElement currentElmt = getAppiumDriver().findElement(By.name(currentCheckin)); swipeFunctionality(currentElmt, checkOutElmt); } else if (checkInMonth.equals(checkOutMonth) || nextToCheckInMonth.equalsIgnoreCase(checkOutMonth)) { checkInElmt.click(); if (tapOrDrag.equalsIgnoreCase("tap")) { checkOutElmt.click(); } else if (tapOrDrag.equalsIgnoreCase("tap and drag")) { swipeFunctionality(checkInElmt, checkOutElmt); } else { swipeFunctionality(nextToCheckInElmt, checkOutElmt); } } else { checkInElmt.click(); if (tapOrDrag.equalsIgnoreCase("tap")) { fillCalendarMonth(checkOutMonth); checkOutElmt.click(); } else if (tapOrDrag.equalsIgnoreCase("tap and drag")) { WebElement middleElmt = findMiddleElement(checkInDate, checkInDay, checkInMonth); swipeFunctionality(checkInElmt, middleElmt); fillCalendarMonth(checkOutMonth); swipeFunctionality(middleElmt, checkOutElmt); } else { WebElement middleElmt = findMiddleElement(checkInDate, checkInDay, checkInMonth); swipeFunctionality(nextToCheckInElmt, middleElmt); fillCalendarMonth(checkOutMonth); swipeFunctionality(middleElmt, checkOutElmt); } }
  • 29.
  • 30.
    Native frameworks • Espresso– Android • Xcode UI testing - iOS
  • 31.
    Espresso • Espresso isan open source Android test automation framework from Google. • Espresso is API for UI Testing on Android. • Espresso core API is small, predictable and easy to learn. • Espresso is a thin layer on top of Android Instrumentation that makes it easy to write reliable UI tests. • It supports all Android versions. • Tests run optimally fast as there is no need for any sleeps (tests run on same millisecond when the app becomes idle)
  • 32.
    Espresso: Code Example publicclass EspressoTest extends ActivityInstrumentationTestCase2<HomeScreenActivity> { public EspressoTest() { super(HomeScreenActivity.class); } @Override public void setUp() throws Exception { super.setUp(); getActivity(); } @Test public void testSearchHotel() { //finding a view with onView and perfoming an action onView(withId(com.hotwire.hotels.R.id.current_location_edittext)) .perform(click()); onView(withId(com.hotwire.hotels.R.id.destination)).perform(typeText("San Francison")); onView(withId(com.hotwire.hotels.R.id.search_hotels_button)).perform(click()); } }
  • 33.
  • 34.
    Xcode UI testing •Available from Xcode 7 • New feature added to XCTest framework • UI recording • Ease to locate elements • Run tests on multiple iOS versions • Integrates with Xcode server • Code coverage
  • 35.
    But why? Wealready have Appium - Faster execution time (1m45sec vs 5m45sec) - Faster to write too (Record feature) - No Appium/3rd party dependencies - Free code coverage reports - Handles wait times implicitly - Snapshot of failed tests - Consolidated reports
  • 36.
    UI testing :Code Example import XCTest class HotwireUITests: XCTestCase { override func setUp() { super.setUp() continueAfterFailure = false XCUIApplication().launch() } func testIPadHotel() { //HomeScreen verification let homeScreen = HomeScreen() homeScreen.verifyHomeScreenElements() //Hotel Search with Signed In User homeScreen.navigateToHotel() //Hotel Farefinder verification let hotelFF = HotelFareFinder() hotelFF.verifyFareFinderElements() hotelFF.findHotel() } import Foundation import XCTest class CarBookingScreen { let elementsQuery = XCUIApplication().scrollViews.otherElements let toolbarsQuery = XCUIApplication().toolbars func goToSignIn(){ elementsQuery.buttons["SIGN IN"].tap() } func completeBooking(){ enterCCV() elementsQuery.switches["AgeRestriction"].tap() elementsQuery.buttons["Book Now"].tap() } }
  • 37.
    Xcode UI testingfor iPad : Demo
  • 38.
    Code coverage -iOS • Tool : LCOV - Collects data from multiple source files , creates HTML pages containing source code annotated with coverage • GitHub - XCodeCoverage - Instrument classes - Run tests - Generate reports(./getcov)
  • 39.
  • 40.
    public class Main{ private String s; public static void main(String[] args){ //some code goes here if (something != null) { //body } } } public class Main { private String s; //magic infused public static void main(String[] args){ //report that method was executed //some code goes here if (something != null) { //report that condition was met //body } } } Original class Instrumented class Code coverage – Android using Emma
  • 41.
    iOS / AndroidCI Goal To provide rapid feedback so that if a bug is introduced into the code base, it can be identified and fixed as soon as possible. Jenkins We are using Jenkins for all our CI runs at the moment, triggered on each Git check-in iOS / Android CI Pipelines • Master Pipeline • Develop Pipeline • Release Pipeline • Feature Pipeline Polling Nodes/hosts from an iOS and Android host-cluster, polled for each leg of the pipeline execution. Artifacts are zipped and transferred between jobs. • Less wait time for resources • Parallel job execution
  • 42.
    iOS CI Build *Unit Tests * iPad Smoke Car/Hotel, iPhone Smoke Car/Hotel * Regression
  • 43.
  • 44.
  • 45.
    Screenshot testing • Imagecomparison – Screen by screen. Why ? – Saves time testing UI layout on various sized screens – New UI bugs caught faster – Helps reduce Regression Cycle Time • ImageMagick tool
  • 46.
  • 47.
    Analytics automation • Loganalytics / tracking information • Read Appium log file • Assert for expected values
  • 48.
    So why arewe doing all this? • Feedback loop – faster @ story level • Regression – 0.5 to 1 day from 5 days • Speed with quality • Visibility
  • 49.
    Hotwire automation framework •To be Open sourced soon. Watch out -> https://github.com/HotwireDotCom/
  • 50.

Editor's Notes

  • #13  ----- Meeting Notes (4/8/14 18:47) ----- Tags @ feature level. applicable to all Scenarios, scenario outline
  • #14  ----- Meeting Notes (4/8/14 18:59) ----- Runtime it passes ios, Android
  • #15  ----- Meeting Notes (4/8/14 18:59) ----- We saw cucumber, Spring config, Java code. Missing part is StepDefs.
  • #19  ----- Meeting Notes (4/8/14 18:59) ----- Runtime it passes ios, Android
  • #20  ----- Meeting Notes (4/8/14 18:47) ----- Spring provides many features. One major one is DI. Easy to implement and integrate with this framework
  • #21  ----- Meeting Notes (4/8/14 18:47) ----- ios implementation Also any user specifc data like user input for user creation
  • #22  ----- Meeting Notes (4/8/14 18:49) ----- Lets look at what is in the HotelImpl.java class
  • #39 Simple script to generate HTML reports of the code coverage. This HTML report is used in Jenkins to show coverage report with every build.
  • #42 What is Continuous Integration (CI)? Isolated changes made by developers are continuously built, tested and reported as and when they are checked in as part of the codebase.