Adi Ben Aroya
Automation Developer
@
On The Agenda
Part I - Intro 
Part II - Technical 
Overview on Gett (GetTaxi)
High level Complexity and Challenges
Automation role and responsibilities in Gett
Selection of tools
Automation Architecture in Gett
Complexity & Solutions (mobile Automation)
Tips & Tricks 
Q&A
Gett
Platform for connecting between supply
and demand for any service.
In other words we are connecting
between consumers and suppliers
ISRAEL UK RUSSIA NYC
50 Cities
Some Numbers...
Under Development In Gett
There are 9 different products...
Android iPhone
Web Sites
B2B Solution/Private Site
Driver Box Tablet
Driver App's
For iPhone
For Android
&
Kiosk
Our Customers
Drivers
Companies
Business Users
Private Users
Complexity & Challenges
Automation Complexity
Multi platforms under same test
Platform/Product synchronization
Challenge to manage small testable units
Challenge managing test run time
Location Location Location
Order Details On Mobile App
In Order Details View alone there are over
50 base permutations based on
configuration and user type.
Different markets, Different Regulations, Different Accountability...
Fix Prices
Internal Meter
External Meter
Taxes
Automation Tools
Selection
As main development language
Object oriented
Fully supports all OS’s
Huge community and open source
support
Android devices and Robotium
Selenium
Runs in many browsers and operating systems
Support many programming languages & testing frameworks.
Open source
Large community
Good documentation
For Headless testing
Based on Selenium
95% Same code
Minimum adaptation & effort
Runs fast
Can Identify problems upon compilation
Robotium
Was the best choice at the time 
Written in Java 
Client/Server Architecture
- Supports real devices & emulators
Supports all API levels 
One of the best solutions for iOS automation today
Large active community
Open Source 
Pause & suggest...
Think about your testing need
functional testing, compatibility testing, UI testing, etc.
And pick up the right and best Android testing framework.
Popular
Reliable
Was the company choice and we aligned with it.
Test manager orchestrator
Work with SUTs
Work with many platforms
Optional support of permutations
Not depended (can be replaced at anytime)
Automation role & responsibility
CI/CD - Automation testing for every commit
Headless testing
End to end testing (Full Regression)
Load testing and performance
Post Production
Roles & Responsibility
Continuous deployment automation
Not Fear Code We Are.
Architecture
SUT
Any platform combination
Creates only the system objects needed.
System Under Test.
Java objects which encapsulates the code
that interacts with the SUT
Device and or software being tested.
SUT Structure
<driverBoxIPhone>
<class>com.gettaxi.automation.gettaxi_auto_infra.mobile.iphone.DriverBoxIphoneImpl</class>
<timeout>60000</timeout>
<device>
<class>com.gettaxi.automation.gettaxi_auto_infra.mobile.iphone.so.IphoneSimulatorSO</class>
<longitude>34.838557</longitude>
<latitude>32.111188</latitude>
<iphoneSimulatorPath>/GetTaxi</iphoneSimulatorPath>
<emulatorName>mobile</emulatorName>
<setLocationOnStart>true</setLocationOnStart>
<running>true</running>
</device> ...
</driverBoxIPhone>
XML configuration file will look like:
The encapsulating Object will be populated at
the @Before stage.
DBX InterFace
Android
Android
Tablet
iPhone
Reflection
Work with interfaces
public interface DriverBoxService {
public enum DriverBoxButton {
CASH, CONFIRM, CREDIT_CARD,PASSENGER_ON_BOARD,
PICKED, REJECT, NO, ACCEPT, ...
}
public String getPrivatePriceFromDBX() throws Exception;
Public void waitForOrder() throws Exception;
Public void goBackToMainScreen() throws Exception;
Public void enterPrice(Integer price) throws Exception;
...
}
Implementors
DBX Android Implementor
public class DriverBoxAndroidImpl extends SystemObjectImpl implements DriverBoxService,
CommunicationListener{
static {
androidButtons = new HashMap<String, String>();
androidButtons.put(DriverBoxButton.ONE_MIN.name(), "com.gettaxi.driverbox:id/btn_1_minute");
androidButtons.put(DriverBoxButton.ARRIVED.name(), "com.gettaxi.driverbox:id/btn_arrived");
}
R class - contains unique id for each view 
public static final int btnYes=0x7f0800b7;
public static final int btn_arrived=0x7f080185;
public static final int btn_busy=0x7f080181;
Implementors
DBX iPhone Implementor
public class DriverBoxIphoneImpl extends SystemObjectImpl implements DriverBoxService
{
static {
iphoneButtons = new HashMap<String, WebLocator>();
iphoneButtons.put(DriverBoxButton.ONE_MIN.name(), orderScreenLocators.ONE_MINUTE);
iphoneButtons.put(DriverBoxButton.ARRIVED.name(), orderScreenLocators.ARRIVED);
Object repository
Implements all Bottons and Methods
Set of inner classed divided by logic
containing all locators.
@Test
@TestProperties(name = "${ManualUcID} - Test Sanity 1 - Private Ride Cash + Coupon", paramsInclude = { "order
"ManualUcID", "tags", "isBrowserNeeded", "driverId"})
public void testSanity_1() throws Exception {
orderPrice = 1;
try {
//since US not accepting cash this is not relevant
if (!GetTaxiSettings.env.name().contains(GetTaxiEnviroment.US.name())){
paymentType = PaymentType.Cash;
initTestParameters(UserType.PRIVATE);
report.startLevel("Launch driver box and GetTaxi app", Reporter.EnumReportLevel.CurrentPlace);
launchDBXAndClientAndDriverLogin();
report.stopLevel();
couponForm.setFirstTimeOnly(false);
String couponExternalId = createCoupon();
orderTaxiForm.setCouponExternalId(couponExternalId);
getTaxiService.addPromotionCode(couponExternalId, true, true);
orderTaxiForm.setPrepaidAccountBalance(getTaxiDBService.getTotalAvailableAmountIncludingCouponsFor
acceptOrderAndPickup(orderTaxiForm, PresentOrFutureRide.NOW, orderPrice);
String orderId = getTaxiDBService.getOrderIdByUser(loginFormMobile.getFirstName());
validateOrderPricesCalculations(getTaxiDBService, ccsDBService, orderId, loginForm, orderTaxiForm,
}
} catch (Exception e) {
fail(e);
}
pass();
}
Work with interfaces
Test Structure
Call to system objects
Tests are organized in classes
based on same business logic (Private, Business, Future )
Initialize test parametrization
Tips & Tricks
iOS - Tables
If Recognized as UIButton but contained in
UITableView handling will be always as table 
MobileElement table = (MobileElement) waitForElement("//UIATableView[1]", 200);
List<WebElement> rows = table.findElements(By.className("UIAButton"));
switch (tipPrecent) {
case _0:
//clickOnImage(GetTaxiButton.ZERO_TIP);
rows.get(0).click();
break;
case _10:
//clickOnImage(GetTaxiButton.TEN_TIP);
rows.get(1).click();
break;
case _12:
//clickOnImage(GetTaxiButton.TWELVE_TIP);
rows.get(2).click();
break;
case _15:
//clickOnImage(GetTaxiButton.FIFTEEN_TIP);
rows.get(3).click();
break;
default:
break;
}
How To Handle Tables
So we inherit all the abstracts of the
selenium as part of the client object and
enjoy all its capabilities.
Appium as WebDriver
protected AppiumDriver iphoneDriver;
Public WebDriver driver;
AppiumDriver extends RemoteWebDriver
Using the api of the web driver
Public AppiumDrivePageImpl pageImpl
public class AppiumDrivePageImpl extends AbstractPage {
/**/
public AppiumDrivePageImpl(WebDriver driver) throws Exception {
super(driver);
if (!isInModule()) {
throw new NotInModuleException(ErrorMessages.NOT_IN_MODULE + getClassName(this));
}
}
@Override
public boolean isInModule() throws Exception {
return true;
}
}
Appium as WebDriver
Based on the PageObject practice created that inherit
from our Abstract Page.
if (isAppiumActive && !isIphoneSimActive) {
iphoneDriver = getTaxiAppium.connect();
device.setIphoneDriver(iphoneDriver);
driver = iphoneDriver;
pageImpl = new AppiumDrivePageImpl(driver);
}
On Appium Loading
public void clickOnImage(GetTaxiButton getTaxiButton, long timeout)
throws Exception {
waitForView(getTaxiButton, timeout);
report.report("Click on button: " + getTaxiButton.name());
pageImpl.clickOnButton(iphoneButtons.get(getTaxiButton.name()));
}
Usage Example
Usage Example
public void clickOnButton(WebLocator webLocator) throws Exception {
Try {
report.report("Click on button: " + webLocator);
printWebLocatorDetails(webLocator);
WebElement element = waitForVisibilityOfElement(webLocator);
clickOnButton(element);
report.report("button: "+ webLocator.getName() + " " + webLocator.getLocator() +" was clicked");
} catch (Exception e) {
report.report("Exception caught in Click on button: " + e.getMessage());
throw e;
}
}
Web implementation of clickOnButton 
Set Location Appium
public void setLocation(double latitude, double longitude, double altitude) {
Location location = new Location(latitude,longitude,altitude);
iphoneDriver.setLocation(location);
report.report("set location in Sim : " + latitude +","+ longitude);
}
public void setLocation(Location location) {
RemoteLocationContext locationContext.setLocation(location);
}
NO DRESS CODE
JUST CODE
Automation Developer? Join The Ride!
CV: Adib@gett.com

Gett - Mobile automation 2015

  • 2.
  • 3.
    On The Agenda PartI - Intro  Part II - Technical  Overview on Gett (GetTaxi) High level Complexity and Challenges Automation role and responsibilities in Gett Selection of tools Automation Architecture in Gett Complexity & Solutions (mobile Automation) Tips & Tricks  Q&A
  • 4.
    Gett Platform for connectingbetween supply and demand for any service. In other words we are connecting between consumers and suppliers
  • 5.
    ISRAEL UK RUSSIANYC 50 Cities
  • 6.
  • 7.
    Under Development InGett There are 9 different products... Android iPhone
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
    Automation Complexity Multi platformsunder same test Platform/Product synchronization Challenge to manage small testable units Challenge managing test run time Location Location Location
  • 19.
    Order Details OnMobile App In Order Details View alone there are over 50 base permutations based on configuration and user type.
  • 20.
    Different markets, DifferentRegulations, Different Accountability... Fix Prices Internal Meter External Meter Taxes
  • 22.
  • 23.
    As main developmentlanguage Object oriented Fully supports all OS’s Huge community and open source support Android devices and Robotium
  • 24.
    Selenium Runs in many browsersand operating systems Support many programming languages & testing frameworks. Open source Large community Good documentation
  • 25.
    For Headless testing Basedon Selenium 95% Same code Minimum adaptation & effort Runs fast Can Identify problems upon compilation
  • 26.
    Robotium Was the bestchoice at the time  Written in Java  Client/Server Architecture - Supports real devices & emulators Supports all API levels 
  • 27.
    One of thebest solutions for iOS automation today Large active community Open Source 
  • 28.
    Pause & suggest... Thinkabout your testing need functional testing, compatibility testing, UI testing, etc. And pick up the right and best Android testing framework.
  • 29.
    Popular Reliable Was the companychoice and we aligned with it.
  • 30.
    Test manager orchestrator Workwith SUTs Work with many platforms Optional support of permutations Not depended (can be replaced at anytime)
  • 31.
    Automation role &responsibility
  • 32.
    CI/CD - Automationtesting for every commit Headless testing End to end testing (Full Regression) Load testing and performance Post Production Roles & Responsibility
  • 33.
  • 34.
  • 35.
  • 36.
    SUT Any platform combination Createsonly the system objects needed. System Under Test. Java objects which encapsulates the code that interacts with the SUT Device and or software being tested.
  • 37.
  • 38.
  • 39.
    Work with interfaces publicinterface DriverBoxService { public enum DriverBoxButton { CASH, CONFIRM, CREDIT_CARD,PASSENGER_ON_BOARD, PICKED, REJECT, NO, ACCEPT, ... } public String getPrivatePriceFromDBX() throws Exception; Public void waitForOrder() throws Exception; Public void goBackToMainScreen() throws Exception; Public void enterPrice(Integer price) throws Exception; ... }
  • 40.
    Implementors DBX Android Implementor publicclass DriverBoxAndroidImpl extends SystemObjectImpl implements DriverBoxService, CommunicationListener{ static { androidButtons = new HashMap<String, String>(); androidButtons.put(DriverBoxButton.ONE_MIN.name(), "com.gettaxi.driverbox:id/btn_1_minute"); androidButtons.put(DriverBoxButton.ARRIVED.name(), "com.gettaxi.driverbox:id/btn_arrived"); } R class - contains unique id for each view  public static final int btnYes=0x7f0800b7; public static final int btn_arrived=0x7f080185; public static final int btn_busy=0x7f080181;
  • 41.
    Implementors DBX iPhone Implementor publicclass DriverBoxIphoneImpl extends SystemObjectImpl implements DriverBoxService { static { iphoneButtons = new HashMap<String, WebLocator>(); iphoneButtons.put(DriverBoxButton.ONE_MIN.name(), orderScreenLocators.ONE_MINUTE); iphoneButtons.put(DriverBoxButton.ARRIVED.name(), orderScreenLocators.ARRIVED); Object repository Implements all Bottons and Methods Set of inner classed divided by logic containing all locators.
  • 42.
    @Test @TestProperties(name = "${ManualUcID}- Test Sanity 1 - Private Ride Cash + Coupon", paramsInclude = { "order "ManualUcID", "tags", "isBrowserNeeded", "driverId"}) public void testSanity_1() throws Exception { orderPrice = 1; try { //since US not accepting cash this is not relevant if (!GetTaxiSettings.env.name().contains(GetTaxiEnviroment.US.name())){ paymentType = PaymentType.Cash; initTestParameters(UserType.PRIVATE); report.startLevel("Launch driver box and GetTaxi app", Reporter.EnumReportLevel.CurrentPlace); launchDBXAndClientAndDriverLogin(); report.stopLevel(); couponForm.setFirstTimeOnly(false); String couponExternalId = createCoupon(); orderTaxiForm.setCouponExternalId(couponExternalId); getTaxiService.addPromotionCode(couponExternalId, true, true); orderTaxiForm.setPrepaidAccountBalance(getTaxiDBService.getTotalAvailableAmountIncludingCouponsFor acceptOrderAndPickup(orderTaxiForm, PresentOrFutureRide.NOW, orderPrice); String orderId = getTaxiDBService.getOrderIdByUser(loginFormMobile.getFirstName()); validateOrderPricesCalculations(getTaxiDBService, ccsDBService, orderId, loginForm, orderTaxiForm, } } catch (Exception e) { fail(e); } pass(); } Work with interfaces
  • 43.
    Test Structure Call tosystem objects Tests are organized in classes based on same business logic (Private, Business, Future ) Initialize test parametrization
  • 44.
  • 45.
    iOS - Tables IfRecognized as UIButton but contained in UITableView handling will be always as table 
  • 46.
    MobileElement table =(MobileElement) waitForElement("//UIATableView[1]", 200); List<WebElement> rows = table.findElements(By.className("UIAButton")); switch (tipPrecent) { case _0: //clickOnImage(GetTaxiButton.ZERO_TIP); rows.get(0).click(); break; case _10: //clickOnImage(GetTaxiButton.TEN_TIP); rows.get(1).click(); break; case _12: //clickOnImage(GetTaxiButton.TWELVE_TIP); rows.get(2).click(); break; case _15: //clickOnImage(GetTaxiButton.FIFTEEN_TIP); rows.get(3).click(); break; default: break; } How To Handle Tables
  • 47.
    So we inheritall the abstracts of the selenium as part of the client object and enjoy all its capabilities. Appium as WebDriver protected AppiumDriver iphoneDriver; Public WebDriver driver; AppiumDriver extends RemoteWebDriver Using the api of the web driver
  • 48.
    Public AppiumDrivePageImpl pageImpl publicclass AppiumDrivePageImpl extends AbstractPage { /**/ public AppiumDrivePageImpl(WebDriver driver) throws Exception { super(driver); if (!isInModule()) { throw new NotInModuleException(ErrorMessages.NOT_IN_MODULE + getClassName(this)); } } @Override public boolean isInModule() throws Exception { return true; } } Appium as WebDriver Based on the PageObject practice created that inherit from our Abstract Page.
  • 49.
    if (isAppiumActive &&!isIphoneSimActive) { iphoneDriver = getTaxiAppium.connect(); device.setIphoneDriver(iphoneDriver); driver = iphoneDriver; pageImpl = new AppiumDrivePageImpl(driver); } On Appium Loading
  • 50.
    public void clickOnImage(GetTaxiButtongetTaxiButton, long timeout) throws Exception { waitForView(getTaxiButton, timeout); report.report("Click on button: " + getTaxiButton.name()); pageImpl.clickOnButton(iphoneButtons.get(getTaxiButton.name())); } Usage Example
  • 51.
    Usage Example public voidclickOnButton(WebLocator webLocator) throws Exception { Try { report.report("Click on button: " + webLocator); printWebLocatorDetails(webLocator); WebElement element = waitForVisibilityOfElement(webLocator); clickOnButton(element); report.report("button: "+ webLocator.getName() + " " + webLocator.getLocator() +" was clicked"); } catch (Exception e) { report.report("Exception caught in Click on button: " + e.getMessage()); throw e; } } Web implementation of clickOnButton 
  • 52.
    Set Location Appium publicvoid setLocation(double latitude, double longitude, double altitude) { Location location = new Location(latitude,longitude,altitude); iphoneDriver.setLocation(location); report.report("set location in Sim : " + latitude +","+ longitude); } public void setLocation(Location location) { RemoteLocationContext locationContext.setLocation(location); }
  • 54.
    NO DRESS CODE JUSTCODE Automation Developer? Join The Ride! CV: Adib@gett.com