Gett - Mobile automation 2015

Preview:

Citation preview

Adi Ben Aroya

Automation Developer

@

On The AgendaPart I - Intro 

Part II - Technical 

Overview on Gett (GetTaxi)High level Complexity and Challenges

Automation role and responsibilities in GettSelection of tools

Automation Architecture in GettComplexity & Solutions (mobile Automation) Tips & Tricks  Q&A

GettPlatform for connecting between supply

and demand for any service.

In other words we are connectingbetween consumers and suppliers

ISRAEL UK RUSSIA NYC

50 Cities

Some Numbers...

Under Development In GettThere are 9 different products...

Android iPhone

Web SitesB2B 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 over50 base permutations based on

configuration and user type.

Different markets, Different Regulations, Different Accountability...

Fix Prices

Internal Meter

External Meter

Taxes

Automation ToolsSelection

As main development language

Object oriented

Fully supports all OS’s

Huge community and open sourcesupport

Android devices and Robotium

SeleniumRuns 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

RobotiumWas 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 codethat 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 atthe @Before stage.

DBX InterFace

Android

AndroidTablet

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;...

}

ImplementorsDBX 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;

ImplementorsDBX 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 logiccontaining all locators.

@Test@TestProperties(name = "${ManualUcID} - Test Sanity 1 - Private Ride Cash + Coupon", paramsInclude = { "orderPrice", "loginForm", "originAddress", "destinationAddress",

"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.getTotalAvailableAmountIncludingCouponsForUser(loginFormMobile.getUserId()));

acceptOrderAndPickup(orderTaxiForm, PresentOrFutureRide.NOW, orderPrice);String orderId = getTaxiDBService.getOrderIdByUser(loginFormMobile.getFirstName());validateOrderPricesCalculations(getTaxiDBService, ccsDBService, orderId, loginForm, orderTaxiForm, orderPrice); }

} catch (Exception e) {fail(e);

}pass();

}

Work with interfaces

Test Structure

Call to system objects

Tests are organized in classesbased on same business logic (Private, Business, Future )

Initialize test parametrization

Tips & Tricks

iOS - Tables

If Recognized as UIButton but contained inUITableView 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 theselenium as part of the client object andenjoy 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 inheritfrom 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 CODEJUST CODE

Automation Developer? Join The Ride!CV: Adib@gett.com

Recommended