The post Hello Appium, Part 1: What is Appium? An Introduction to Appium and its Tooling appeared first on Automated Visual Testing | Applitools.
]]>In the first article in this series, learn how to get started with Appium. We’ll dig into what Appium is, the essentials of the Appium architecture and how you can use Appium to solve your mobile test automation issues today. You can also skip ahead to read about how to set up your first Appium Android test and how to set up your first Appium iOS test.
I recently had the privilege to speak at Appium Conf 2021 on a topic quite near to my heart: Getting started with Appium.
If you are an intermediate or advanced Appium user, then sure, ?? you may be familiar with this already.
However, I’m a fan of a concept called Shoshin (loosely translated as “Beginner’s mind”) and believe that relearning something opens up new ways of solidifying concepts and often enlightens you about the gaps in your knowledge.
When I started learning Appium back in 2018, I remember I had to struggle a lot to figure out where to start, what setups are needed to run my first test, or just even the underlying architecture.
This was a lot of initial friction and I remember thinking to myself:
It shouldn’t be this hard just to get started, eh?
Appium is a great automation tool and now having used it for a few years and having gone through the trenches I wanted to improve this experience for beginners. Hence the reason for my talk and this blog series. If you are curious about the Appium talk, the video is out on YouTube and slides over a static site.
In this 3 part series we’ll deep dive into:
Let’s begin.
Appium is an open source ecosystem of tools and libraries that help you drive your mobile apps (native, hybrid, and mobile web on platforms such as Android, iOS), desktop apps (Windows, Mac), and now even on platforms like Smart TV and much more ?.
Language agnostic: With Appium you can choose the language binding of your choice (Such as Java, Kotlin, Python, JavaScript, Ruby, C# … ?) and don’t have to be tied to the programming language of the platform vendors (Kotlin, Swift, etc.).
Does not reinvent the wheel: Appium provides a convenient API compliant with Web driver protocol that wraps automation libraries from vendors (Google UIAutomator2/Espresso, Apple XCUITest/UIAutomation, Windows WinApp) and allows you to write cross-platform tests.
No requirement of SDK or recompilation of the app: Appium can drive the app from a grey box user perspective but does not need any app compilation step.
Cross-platform: Drives apps on different platforms and provided apps have the same business logic, could drive them with a single cross-platform test.
Before diving into practical setup and tests, it’s important to understand the Appium ecosystem in a birds-eye so that you can make sense of all the different components at play
The below high-level architecture diagram gives the perspective:
The core components are:
A typical request in Appium loosely looks like below:
{
"orientation": "LANDSCAPE|PORTRAIT"
}
Now that we understand the high-level components at play, let’s install some of these to set up our environment regardless of the platform that we choose to automate.
To set up the Appium server and other utilities, we’ll need to install npm, node. These could be easily installed with a tool like homebrew (mac), Linux brew (Linux), or chocolatey (windows)
We’ll assume using a Mac/Linux or WSL (Windows Subsystem for Linux) environment for this series but you’ll be able to find equivalent steps for the Windows platform by googling.
We’ll need it to install npm and node.
To install on macOS:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
On Linux or WSL (Windows Subsystem for Linux), you may need to install Linux brew.
You can download and install node (10+) for your platform. Prefer choosing LTS (Long term support version) since that would be the stable version.
On macOS:
brew install node
Verify running the below command returns desired version:
node -v
And verify that npm is installed as well:
npm -v
To install Appium server < 2.0
npm install -g appium
Verify Appium server is installed by typing appium command in your terminal and see all server logs.
➜ appium-fast-boilerplate git:(main) appium
[Appium] Welcome to Appium v1.17.0
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
Appium 1.2x.x would be the last version supported by Appium devs and an EOL (End of Life) plan is already published on the Appium Github repo. Read it here. Since Appium 2.0 is the future of the project, let’s see how to install the new server and some key commands.
To install Appium 2.0:
npm install -g appium@next
You’ll get an output like:
/usr/local/bin/appium -> /usr/local/lib/node_modules/appium/build/lib/main.js
> appium@2.0.0-beta.16 postinstall /usr/local/lib/node_modules/appium
> node ./postinstall.js
Not auto-installing any drivers or plugins
+ appium@2.0.0-beta.16
added 113 packages from 587 contributors, removed 316 packages, updated 136 packages and moved 5 packages in 81.611s
With Appium 2.0, drivers are decoupled and not bundled into the main server. This makes sense since if your app is only on Android, you wouldn’t need iOS, desktop, and TV drivers anyways right?
We’ll install Android and iOS drivers for this project using the below commands:
appium driver install xcuitest
appium driver install uiautomator2
You can list all available drivers using the command:
appium driver list
Or list only installed drivers using:
appium driver list --installed
After running the appium command, you’ll see an output like this and as you can see our installed drivers:
[Appium] Welcome to Appium v2.0.0-beta.16
[Appium] Non-default server args:
[Appium] tmpDir: /var/folders/5d/flg6q03n3j7769kffzly2x_r0000gp/T
[Appium] Attempting to load driver xcuitest...
[Appium] Attempting to load driver uiautomator2...
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
[Appium] Available drivers:
[Appium] - xcuitest@3.53.1 (automationName 'XCUITest')
[Appium] - uiautomator2@1.67.0 (automationName 'UiAutomator2')
You can install Java from the Oracle site or the OpenJDK version:
On macOS: If you choose to install OpenJDK, then execute the below command:
brew install openjdk@8
sudo ln -sfn /usr/local/opt/openjdk@8/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-8.jdk
Add JDK home path as JAVA_HOME variable. Since we would use the Java client binding for this series, this is a needed step.
export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk-8.jdk/Home
export PATH=$JAVA_HOME/bin:$PATH
Appium doctor is a CLI that provides insights on what dependencies are missing as well as how to install them. It even provides very helpful suggestions or notes on how exactly a dependency might be useful.
Make sure all required dependencies are installed:
npm install -g appium-doctor
Run below commands:
# For both android and iOS
appium-doctor
# For only android
appium-doctor --android
# For only iOS
appium-doctor --ios
If I run it at this point in time, it intelligently warns me about the required dependencies that are installed, optional dependencies that could be installed, and how to go about installing them.
So hopefully you are set up with Appium, have a conceptual understanding of the different components, and are now ready to dive into writing our first tests for Android and iOS. Stay tuned for the next part. In the meantime, you can read the below docs to get further context.
Looking for more? We’ve got other great content to help you dig in and get started with Appium. Here are a few places to help you get started with Appium today.
The post Hello Appium, Part 1: What is Appium? An Introduction to Appium and its Tooling appeared first on Automated Visual Testing | Applitools.
]]>The post How to Build Your Own Appium Plugin appeared first on Automated Visual Testing | Applitools.
]]>In the previous blog post we discussed Appium 2.0 Drivers and Plugins usage and its installation. This article is aimed at creating your own Appium Plugin and its use cases.
Appium plugins are here to help with the various use cases that require a change to Appium’s default behavior.
There are already official Appium plugins created by the project, as well as community-created Appium plugins.
Let’s say we want to improve the way we write appium tests, for example, let appium server take care of element waits and we focus on the user journey in tests rather than element waits all over it.
Below are the steps to create a new plugin to wait for the presence of an element:
Initialize a new node project
npm init
Install Appium base plugin as a dependency inside the new project created in above step
npm i @appium/base-plugin
Navigate to the package.json and add an appium object as described below:
"appium": {
"pluginName": "element-wait",
"mainClass": "WaitCommandPlugin"
}
Create a new file called plugin.js in the root directory of the project
In plugin.js, create a class which extends appium base plugin.
export default class WaitCommandPlugin extends BasePlugin {}
Here is the list of supported Appium commands. As per our use case, we need to override the appium findElement command.
Override the appium command implementation in our new class
async findElement(next, driver, ...args) {
// Custom Implementation of Appium’s FindElement command
}
We can extract strategy and selector from the arguments of the findElement command and then make an API call to the /element endpoint to check if it exists in the DOM (document object model):
const response = await fetch(
`${baseUrl}wd/hub/session/${this.driver.sessionId}/element`,
{
body: JSON.stringify({
strategy: this.strategy,
selector: this.selector,
context: '',
multiple: false,
}),
method: 'POST',
headers: { 'Content-Type': 'application/json' },
}
);
Keep polling the endpoint consistently for a constant period of time until the element exists, if it exists check for element displayed status as below:
const response = await fetch(
`${baseUrl}wd/hub/session/${this.driver.sessionId}/element/${this.element}/attribute/displayed`,
{
method: 'GET',
headers: { 'Content-Type': 'application/json' },
}
);
return await response.json();
}
Call await next() to execute the default behaviour of the findElement command. Refer here for more details on plugin.js
Export the plugin
Create a new file called index.js in the root directory of the project to export the plugin
export default WaitCommandPlugin;
Install the plugin
Transpile and build the plugin using babel or Typescript. Install the plugin from local source using the below command:
appium plugin install --source=local <path to plugin>
Activate the plugin
The plugin can be activated using the following command while starting the Appium server. In this example, “element-wait” is the name of the plugin.
appium --plugins=element-wait
Plugin usage
The element wait plugin is activated while starting the appium server so the client code can be simplified without using webdriver waits.
Without Wait plugin
wait = new WebDriverWait(driver, 30);
wait.until(presenceOfElementLocated(MobileBy.AccessibilityId("login"))).click();
wait.until(presenceOfElementLocated(MobileBy.AccessibilityId("slider")));
driver.findElementByAccessibilityId("slider").click();
With Wait plugin
driver.findElementByAccessibilityId("login").click();
driver.findElementByAccessibilityId("slider").click();
In the example above, we altered the existing appium command to find an element, but Appium plugins can also be used to create our own custom commands on top of Appium supported commands.
To implement custom commands or adding new routes in appium we need to implement on both the Appium server and client-side.
A server-side plugin includes adding a new method map where we define the route and the new Appium command and its implementation.
static newMethodMap = {
'/session/:sessionId/fake_data': {
GET: {command: 'getFakeSessionData'}
},
};
async getFakeSessionData (next, driver) {
await B.delay(1);
return driver.fakeSessionData || null;
}
As of today custom commands can be added only in Appium Ruby, Appium Python and in WebdriverIO. Below is an example from Appium Ruby client:
@driver.add_command(
method: :post,
url: 'session/:session_id/path/to/custom/bug/report,
name: :bug_report
) do
def bug_report(argument)
execute(:bug_report, {}, { sample: argument })
end
end
@driver.bug_report(1)
Using this approach, the Appium plugin adds custom commands and overrides or modifies the existing Appium commands.
Decoupled Appium 2.0 architecture will help create new plugins to solve many interesting use cases. For more on Appium 2.0, check out our talk at the Future of Testing event.
The post How to Build Your Own Appium Plugin appeared first on Automated Visual Testing | Applitools.
]]>