Migrate Appium java-client v7 to v8

     We know that Appium java-client libraries wrap standard Selenium client libraries to provide all the regular selenium commands dictated by the JSON Wire Protocol and add extra commands related to controlling mobile devices, such as multi-touch gestures and screen orientation. Appium java-client is the Java language binding for writing Appium tests, conforming to Mobile JSON Wire Protocol.

     In this article, I would like to share the main changes between java-client versions 7 and 8. This should help everyone to successfully migrate the existing automated tests codebase. The java client 7.6.0 was the last 7.x version and in 2022-Q1, they released the stable 8.0.0 version of the java-client with exciting features that support Appium server 2.x. This is a good time to migrate the java-client v7 to v8 since we are all moving from Appium Server 1.x to 2.x. Following are the main changes when you are migrating from java-client v7 to v8,

W3C specification compatibility

     Java client now supports Selenium 4, which also means it is strictly W3C compliant. Old JSON Wire Protocol-based servers are not supported anymore, and it won’t be possible to use the new client version with them. Capabilities that enforce the usage of JSON Wire Protocol on Appium drivers don’t have any effect anymore.

     The recommended way to provide capabilities for driver creation is to use specific option builders inherited from BaseOptions class. For example, XCUITestOptions to create an XCUITest driver instance or UiAutomator2Options to create an UiAutomator2 driver instance. If there is no driver-specific options class for your driver then either use BaseOptions builder as the base class to define your capabilities. Do not use DesiredCapabilities class for this purpose in the W3C context.

Elements lookup

Let’s discuss the changes in element lookup,

  • All findBy* shortcut methods were removed. Consider using findElement[s](By. or AppiumBy.) instead.
  • MobileBy class has been deprecated. Consider using AppiumBy instead.
  • All locator names in AppiumBy have been aligned to follow the common (camelCase) naming strategy, e.g. MobileBy.AccessibilityId was changed to AppiumBy.accessibilityId.
  • The changes made in Selenium 4 broke class name selector strategy in Appium. AppiumBy.className should be used instead of Selenium’s By.className now.
Changes in Time

     All methods that use TimeUnit class or where the time is passed as a simple numeric value were replaced with their alternatives using java.time.Duration class.

Events Firing

     The current event firing mechanism that the Appium java client uses has been deprecated in favor of the one that Selenium 4 provides natively. The event firing feature allows the end-user to organize the event logging on the client-side. Also, this feature may be useful in binding with standard or custom reporting frameworks. The feature has been introduced first since Selenium API v4. There are two main entities used to implement events firing logic: EventFiringDecorator and WebDriverListener.

     Classes that implement WebDriverListener interface are intended to be used with EventFiringDecorator. This interface provides an empty default implementation for all methods that do nothing. You could easily extend that interface to add more methods. The strategy to add new/custom event listeners is the following. Let’s say there is a public setOrientation method in the target WebDriver instance. Then you’d have to add beforeSetOrientation and/or afterSetOrientation methods to your WebDriverListener descendant accepting a single argument of WebDriver type. If the target method accepts one or more arguments then these arguments should also be added to the event listeners in the same order they are accepted by the original method, but the very first argument should still be the firing WebDriver instance. Make sure that your implementation of WebDriverListener class is public and that event listener methods are also public.

     EventFiringDecorator creates a wrapper around an arbitrary WebDriver instance that notifies registered listeners about events happening in this WebDriver and derived objects, such as WebElements and Alert. Listeners should implement WebDriverListener. It supports three types of events:

  • “before”-event: a method is about to be called.
  • “after”-event: a method was called successfully and returned some result.
  • “error”-event: a method was called and thrown an exception.

     To use this decorator you have to prepare a listener, create a decorator using this listener, decorate the original WebDriver instance with this decorator and use the new WebDriver instance created by the decorator instead of the original one. Following is the sample snippet:

WebDriver original = new AndroidDriver();
// it is expected that MyListener class implements WebDriverListener
// interface or its descendant
WebDriverListener listener = new MyListener();
WebDriver decorated = new EventFiringDecorator(listener).decorate(original);
// the next call is going to fire:
// - beforeAnyCall
// - beforeAnyWebDriverCall
// - beforeGet
// - afterGet
// - afterAnyWebDriverCall
// - afterAnyCall
// events in the listener instence (in this order)
decorated.get("https://journeyofquality.com/");
// the next call is going to fire:
// - beforeAnyCall
// - beforeAnyWebDriverCall
// - beforeFindElement
// - afterFindElement
// - afterAnyWebDriverCall
// - afterAnyCall
// events in the listener instence (in this order)
WebElement header = decorated.findElement(By.tagName("h1"));
// if an error happens during any of these calls the the onError event is fired
AppiumDriver

     All AppiumDriver descendants and the base class itself are not generic anymore and work with WebElement interface only. The base Appium driver does not extend ContextAware, Rotatable, and other mobile-specific interfaces. Instead, it only has a very basic set of methods. Mobile-specific extensions have been respectively moved to IOSDriver and AndroidDriver.

     Removed the obsolete HasSessionDetails extensions as it was using legacy JWP calls to retrieve session details. DefaultGenericMobileDriver class has been removed. Now AppiumDriver is inherited directly from Selenium’s RemoteWebDriver.

MobileElement

     DefaultGenericMobileElement class has been removed completely together with its descendants (MobileElement, IOSElement, AndroidElement etc.). Use WebElement instead. Due to this change, the page factory is now only creating elements that are instantiated from RemoteWebElement and implement WebElement interface. If you used some special methods that MobileElement or its descendants provided then change these:

  • replaceValue has been moved to the corresponding AndroidDriver instance and is called now replaceElementValue.
  • Use the sendKeys method of the WebElement interface instead of setValue.
Touch Actions

     The TouchAction and MultiTouchAction classes have been deprecated. The support for these actions will be removed from future Appium versions. Please use W3C Actions instead or the corresponding extension methods for the driver.

resetApp/launchApp/closeApp

     AppiumDriver methods resetApp, launchApp and closeApp have been deprecated as they are going to be removed from future Appium versions.

AppiumDriverLocalService

     The default URL the server is listening on has been changed, and it does not contain the /wd/hub suffix anymore (e.g. http://0.0.0.0:4723/wd/hub became http://0.0.0.0:4723/). This has been done in order to align the actual behavior with Appium v2.

     If you still would like to use v8 of the Java client with Appium v1.2x, where the server URL contains the /wd/hub suffix by default, then consider providing –base-path setting explicitly while building AppiumServiceBuilder instance (e.g. .withArgument(GeneralServerFlag.BASEPATH, “/wd/hub/”)). Older versions of the Appium server (v1.19 and older) won’t work with AppiumDriverLocalService, because they don’t allow provisioning of the base path in form of a command-line argument.

     Thanks for reading this article and I hope you got some idea prior to migrating the java-client v7 to v8. Consider all the above changes while migrating the java-client v7 to v8.

make it perfect!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: