I found Appium very cumbersome when testing mobile web applications because touch actions are not well supported. From a Java perspective, I found there two main options for communicating with Appium: Selenium RemoteWebDriver and AppiumDriver from the Appium Java client .
Selenium RemoteWebDriver
So far, I have been able to test our web application on an Android device using the selenium RemoteWebDriver and RemoteTouchScreen. Using Selenium 3.6.0 and Appium 1.6.5, I tested 4 different methods to click an element:
webDriver.findElement(locator).click(); new Actions(webDriver).moveToElement(findElement(locator)).click().perform(); new RemoteTouchScreen(new RemoteExecuteMethod(webDriver)).singleTap(((Locatable)webDriver.findElement(locator)).getCoordinates()); new TouchActions(webDriver).singleTap(locator);
On Android, the first three methods work, but 4 throws a "not supported" exception. I decided to use method 1 for clicks / taps and 3 for gestures.
On iOS, methods 1, 2, and 4 throw an โnot yet supportedโ exception, and method 3 does nothing. Since I was not ready to spend time troubleshooting, we are only testing Android now, hoping the Appium will be improved and iOS will be better supported.
Appium Java Client
My experience with the Appium java client (version 5.0.4) was even worse. There seems to be no comprehensive tutorial on how to do sensory actions, only a few pieces of code flying around firewalls. Therefore, my answer to this question is an attempt to create it.
First create an instance of the driver and go to the page:
DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName", "Samsung Android S8"); capabilities.setCapability("browserName", "Chrome"); capabilities.setCapability("platformName", "Android"); MobileDriver appiumDriver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); appiumDriver.navigate().to("https://duckduckgo.com");
Then do the touch action:
new TouchAction(appiumDriver).tap(appiumDriver.findElement(By.id("search_form_input_homepage"))).perform();
The result is: org.openqa.selenium.WebDriverException: the method has not yet been implemented.
From this forum post I realized that I need to switch context in order to be able to do sensory actions. Try two:
appiumDriver.context("NATIVE_APP"); new TouchAction(appiumDriver).tap(appiumDriver.findElement(By.id("search_form_input_homepage"))).perform();
It works. However, only for the By.id. selector. I could not find any other selector that works in the context of NATIVE_APP. And since most elements of our website lack an identifier, I need an xpath selector. Try three:
appiumDriver.context("NATIVE_APP"); new TouchAction(appiumDriver).tap(appiumDriver.findElement(By.xpath("//*[@id=\"search_form_input_homepage\"]"))).perform();
The result is: org.openqa.selenium.NoSuchElementException: the element could not be found on the page using the specified search parameters.
Other workarounds that I could come up with, such as selecting a WebElement in the CHROMIUM context and then moving the location to the NATIVE_APP context, is not an option as the coordinate systems are different (browser pixels and screen pixels).
And don't forget to revert to the default CHROMIUM standard after each touch action. Thus, the full code of only a working example will look like this:
try { appiumDriver.context("NATIVE_APP"); new TouchAction(appiumDriver).tap(appiumDriver.findElement(By.id("search_form_input_homepage"))).perform(); } finally { appiumDriver.context("CHROMIUM"); }
At this point, I came to the conclusion that testing mobile web applications with Appium is not yet complete.