Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

iOS and Android apps automation

962 views

Published on

Silicon valley code camp 2015

Published in: Mobile

iOS and Android apps automation

  1. 1. iOS and Android Apps automation By, Sridhar Ramakrishnan Life long travel geek @ Hotwire Inc.
  2. 2. 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??
  3. 3. 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
  4. 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. 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. 6. Test Automation
  7. 7. 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
  8. 8. Test Automation @ Hotwire • Test Framework = Hotwire BDD • Tools = Xcode UI testing • API = Spoofer (mock) vs API calls
  9. 9. Appium – Multi OS Support And More…
  10. 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. 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. 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. 13. 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(); }
  14. 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. 15. Screen Objects - iOS // iOS Screen Object public class iOSSearchScreen extends AbstractScreen { @FindBy(name = ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
  16. 16. Screen Objects - Android // Android Screen object public class AndroidSearchScreen extends AbstractScreen { @FindBy(id= ”Search") private WebElement searchBtn; public void search() { searchBtn.click(); } }
  17. 17. 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; } }
  18. 18. 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(); }
  19. 19. Dependency Injection using Spring Framework Context file - Cucumber.xml <context:component-scan base-package="com.test" /> <import resource="cucumber-${mobileOS}.xml"/>
  20. 20. 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">
  21. 21. 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">
  22. 22. Managing Dependency 3rd Party Jars Cucumber Spring Reporting Junit / testng … Tests Jars Features StepDefs iOS-Screen-Objects Android-Screen-Objects …
  23. 23. 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
  24. 24. Appium locator & tools WebDriver Locators : • ID • Name • Xpath Tools : • Appium inspector (iOS) • Uiautomatorviewer (Android)
  25. 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. 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); }
  27. 27. 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); } }
  28. 28. iOS Demo
  29. 29. Native frameworks • Espresso – Android • Xcode UI testing - iOS
  30. 30. 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)
  31. 31. 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()); } }
  32. 32. Android Demo
  33. 33. 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
  34. 34. 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
  35. 35. 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() } }
  36. 36. Xcode UI testing for iPad : Demo
  37. 37. 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)
  38. 38. Code coverage - iOS
  39. 39. 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
  40. 40. 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
  41. 41. iOS CI Build * Unit Tests * iPad Smoke Car/Hotel, iPhone Smoke Car/Hotel * Regression
  42. 42. iOS CI • Reporting & Snapshots
  43. 43. iOS CI
  44. 44. 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
  45. 45. CI – Screenshot comparison
  46. 46. Analytics automation • Log analytics / tracking information • Read Appium log file • Assert for expected values
  47. 47. 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
  48. 48. Hotwire automation framework • To be Open sourced soon. Watch out -> https://github.com/HotwireDotCom/
  49. 49. Questions ?

×