Advanced Appium Workshop

Appium Philosophy

 

  • You’re testing the same app you are shipping
  • Write tests in any language and framework you want
  • Wrapped vendor-provided frameworks in WebDriver API (Webdriver Protocol)
  • Open source

Android Architecture

 

W3C

Server Request

Server

Client

Appium Server

Espresso driver

iOS Architecture

 

W3C

Server Request

WDA

Client

Appium Server

XCUI driver

W3C WebDriver Spec

  • WebDriver is a remote control interface that enables introspection and control of user agents.

  • It provides a platform- and language-neutral wire protocol as a way for out-of-process programs to remotely instruct the behavior of web browsers.

  • WebDriver spec grew out of the Selenium project, and that is still the community of users pushing forward the associated browser automation technology and using it every day to write and run automated tests.

  • Browser vendors now also support the WebDriver spec natively.

File appDir = new File("src/test/java/io/appium/java_client");
File app = new File(appDir, "ApiDemos-debug.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("automationName", "UIAutomator2");
capabilities.setCapability("deviceName", "Android Emulator");
capabilities.setCapability("app", app.getAbsolutePath());
driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), 
        capabilities);

W3C WebDriver Spec: Architecture

Client code

Server logs

[debug] [W3C] Calling AppiumDriver.createSession() with args: [{"app":"/Users/ssekar/workspace/VodQaAdvancedAppium/VodQA.apk","newCommandTimeout":700000,"automationName":"UIAutomator2","platformName":"Android","deviceName":"Android Emulator","avd":"Pixel"},null,{"alwaysMatch":{"appium:app":"/Users/ssekar/workspace/VodQaAdvancedAppium/VodQA.apk","appium:automationName":"UIAutomator2","appium:avd":"Pixel","appium:deviceName":"Android Emulator","appium:newCommandTimeout":700000,"platformName":"android"},"firstMatch":[{}]}]
[debug] [BaseDriver] Event 'newSessionRequested' logged at 1538587587745 (22:56:27 GMT+0530 (IST))
[Appium] Creating new AndroidUiautomator2Driver (v1.20.0) session
[Appium] Capabilities:
[Appium]   platformName: android
[Appium]   app: /Users/ssekar/workspace/VodQaAdvancedAppium/VodQA.apk
[Appium]   automationName: UIAutomator2
[Appium]   avd: Pixel
[Appium]   deviceName: Android Emulator
[Appium]   newCommandTimeout: 700000
[debug] [BaseDriver] W3C capabilities {"alwaysMatch":{"platformNa... and MJSONWP desired capabilities {"app":"/Users/ssekar/works... were provided
[debug] [BaseDriver] Creating session with W3C capabilities: {"alwaysMatch":{"platformNa...
[BaseDriver] Session created with session id: 7ffaf9de-f987-4820-9709-4d22195b4968

Android - Espresso

  • Provides automatic synchronization of test actions with UI

  • Powerful Matchers available

  • Access to App internals - WebViews

File appDir = new File("src/test/java/io/appium/java_client");
File app = new File(appDir, "ApiDemos-debug.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("automationName", AutomationName.ESPRESSO);
capabilities.setCapability("deviceName", "Android Emulator");
capabilities.setCapability("app", app.getAbsolutePath());
driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), 
    capabilities);

Start Appium server programmatically

AppiumDriverLocalService service = AppiumDriverLocalService
    .buildService(new AppiumServiceBuilder()
    .usingAnyFreePort());
service.start();

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability............................
......................................................
driver = new AndroidDriver<MobileElement>(service.getUrl(), 
    capabilities);

Horizontal Swipe using Touch Action

x axis

y axis

(0,0)

(0,H/2)

(W/2,H/2)

press(0,H/2)

wait(seconds)

moveTo(W/2,H/2)

release

perform

ActionsActions API for gestures

Horizontal Swipe using W3C Action API

x axis

y axis

(x1,y1)

(x2,y1)

(0,0)

iOS specific gestures

Map<String, Object> args = new HashMap<>();
args.put("direction", "up");
driver.executeScript("mobile: swipe", args);
args.put("direction", "down");
driver.executeScript("mobile: swipe", args);

mobile: swipe

Map<String, Object> args = new HashMap<>();
args.put("direction", "down");
driver.executeScript("mobile: scroll", args);
args.put("direction", "up");
driver.executeScript("mobile: scroll", args);

mobile: scroll

Map<String, Object> args = new HashMap<>();
args.put("scale", 5);
driver.executeScript("mobile: pinch", args);

mobile: pinch

iOS specific gestures

Map<String, Object> args = new HashMap<>();
args.put("element", ((MobileElement) element).getId());
args.put("x", 2);
args.put("y", 2);
driver.executeScript("mobile: tap", args);

mobile: tap

// double-tap the screen at a specific point
Map<String, Object> args = new HashMap<>();
args.put("x", 100);
args.put("y", 200);
driver.executeScript("mobile: doubleTap", args);

mobile: doubleTap

// two-finger-tap an element (assume element object already
 exists)
Map<String, Object> args = new HashMap<>();
args.put("element", ((MobileElement) element).getId());
driver.executeScript("mobile: twoFingerTap", args);

mobile: twoFingerTap

iOS specific gestures

// touch and hold an element
Map<String, Object> args = new HashMap<>();
args.put("element", ((MobileElement) element).getId());
args.put("duration", 1.5);
driver.executeScript("mobile: touchAndHold", args);

mobile: touchAndHold

// touch, hold, and drag based on coordinates
Map<String, Object> args = new HashMap<>();
args.put("duration", 1.5);
args.put("fromX", 100);
args.put("fromY", 100);
args.put("toX", 300);
args.put("toY", 600);
driver.executeScript("mobile: dragFromToForDuration", args);

mobile:dragFromToForDuration

Android shell interactions

10057 ◯ : adb shell dumpsys battery
Current Battery Service state:
  AC powered: true
  USB powered: false
  Wireless powered: false
  Max charging current: 0
  Max charging voltage: 0
  Charge counter: 0
  status: 2
  health: 2
  present: true
  level: 100
  scale: 100
  voltage: 0
  temperature: 0
  technology: Li-ion

Get Battery Information

10078 ◯ : adb shell dumpsys cpuinfo
Load: 0.0 / 0.0 / 0.0
CPU usage from 312959ms to 312499ms ago (2018-10-07 10:49:37.267 to 2018-10-07 10:49:37.727):
  151% 1523/system_server: 51% user + 100% kernel / faults: 7233 minor 83 major
  15% 1365/surfaceflinger: 6.6% user + 8.8% kernel / faults: 1 minor
  15% 1375/installd: 2.2% user + 13% kernel / faults: 113 minor
  6.6% 1499/bootanimation: 4.4% user + 2.2% kernel
  4.4% 1358/android.hardware.graphics.composer@2.1-service: 2.2% user + 2.2% kernel
  2.2% 1288/kworker/0:1: 0% user + 2.2% kernel
  2.2% 1298/logd: 0% user + 2.2% kernel / faults: 5 minor
  2.2% 1299/servicemanager: 0% user + 2.2% kernel / faults: 1 minor
  2.2% 1360/android.hardware.sensors@1.0-service: 0% user + 2.2% kernel / faults: 20 minor
50% TOTAL: 13% user + 26% kernel + 10% iowait

Get cpu Information

10079 ◯ : adb shell service list

List all services

Platform-wise desired capabilities

Android iOS
skipUnlock usePrebuiltWDA
appWaitPackage derivedDataPath
appWaitActivity useJSONSource
androidInstallTimeout iosInstallPause
disableAndroidWatchers maxTypingFrequency
autoGrantPermission mjpegServerPort
avd wdaLaunchTimeout

Refer: https://appium.io/docs/en/writing-running-appium/caps/

iOS Locator Strategy

http://appium.io/docs/en/writing-running-appium/ios/ios-predicate/

https://github.com/facebook/WebDriverAgent/wiki/Predicate-Queries-Construction-Rules

Predicates

driver.findElementByIosNsPredicate("name like 'Answer'")

class chain

driver.findElementByIosClassChain("**/XCUIElementTypeTable
                [`name == "table"`]/XCUIElementTypeCell[`visible == 1`]")

https://github.com/facebook/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules

https://github.com/facebook/WebDriverAgent/wiki/How-To-Achieve-The-Best-Lookup-Performance#select-the-most-effective-lookup-strategy

 

Accessibility Identifier

driver.findElementByAccessibilityId("ComputeSumButton")

Parallel Test Execution

Android iOS
UDID - Device ID UDID - Real device/SimID
chromedriverport - incase of webviews or chrome wdalocalport - unique port no as WDA defaults to 8100
systemPort - If you are using UIA2 mode, set a different system port for each Appium instance set with systemPort capability since sometimes there can be a port conflict if different ports aren't used, such as in this issue.(https://github.com/appium/appium/issues/7745) deviceName - Simulator Name (sim only)
platformVersion -Simulator OS version (sim only)

Refer: http://appium.io/docs/en/advanced-concepts/parallel-tests/

Thank you

AppiumWorkshop

By Sai Krishna

AppiumWorkshop

  • 1,193