Appium
Introduction:
Appium is an open-source tool for automating native,
mobile web, and hybrid applications on iOS and Android platforms. Native apps
are those written using the iOS or Android SDKs. Mobile web apps are web apps
accessed using a mobile browser (Appium supports Safari on iOS and Chrome or
the built-in ‘Browser’ app on Android). Hybrid apps have a wrapper around a
“webview” – a native control that enables interaction with web content.
Appium Design:
1. Vendor-provided
automation frameworks under the hood:
o iOS: Apple’s UIAutomation
o Android 4.2+: Google’s UiAutomator
o Android 2.3+: Google’s Instrumentation. (Instrumentation
support is provided by bundling a
separate project, Selendroid)
2. Wrapping the vendor-provided frameworks in one API,
the WebDriver API. WebDriver
(aka “Selenium WebDriver”) specifies a client-server protocol (known as the JSON Wire Protocol). Given this
client-server architecture, a client
written in any language can be used to send the appropriate HTTP requests to the server. Appium & WebDriver
clients are not technically
“test frameworks” – they are “automation libraries”.
You can manage your test environment any way you like!
Requirement:
IOS REQUIREMENTS
o Mac OS X 10.9.2 recommended
o XCode >= 5.1.1
recommended
o Apple Developer Tools (iPhone simulator SDK, command line
tools)
ANDROID
REQUIREMENTS
o Android SDK API >= 17 (Additional features require
18/19)
Setup:
Running Appium on
iOS:
Appium on OS X
supports iOS and Android testing.
o Appium requires Mac OS X 10.9 is recommended.
o Make sure you have Xcode
and the iOS SDK(s) installed. Xcode
version 5.1 is recommended.
o Using Appium.app, you can authorize iOS through the GUI.
Check
the below:
o If you’re on Xcode 6, you need to launch each simulator
you intend to use with appium in advance, and change the default to actually
show the soft keyboard if you want
sendKeys to work. You can do this by clicking on any textfield and hitting
command-K until you notice the soft keyboard show up.
o If you’re on Xcode 6, you have a feature in Xcode called
Devices (command-shift-2). You need to make sure that whichever deviceName you choose to use with Appium in
your capabilities, there is only one of those per sdk version. In other words,
if you send in a deviceName cap of “iPhone
5s” and a platformVersion cap of “8.0”, you need to make sure that there is exactly one device with the
name “iPhone 5s” and the 8.0 sdk in
your devices list. Otherwise, Appium won’t know which one to use.
o In iOS8, devices each have their own setting which
enables or disables UIAutomation. It lives in a “Developer” view in the
Settings app. You need to
verify that UIAutomaion is enabled in this view before the simulator or device can be automated.
Running
Appium on Android:
If
you are running Appium on Windows, you can use the Appium.exe client, which will allow you to quickly launch an Appium server and use the Inspector. You will
not be able to test iOS apps on a locally
hosted server, because Appium relies on OS X-only libraries to support iOS testing. You can however
use the Remote Server option to connect
to an Appium server running on a Mac.
Deploying an iOS app to a real device:
To prepare for your Appium tests to run on a real device,
you will need to:
o Build your app with specific device-targeted parameters
o Use fruitstrap, a 3rd-party tool, to deploy this build to
your device
Deploying an Android app to a real device:
Appium GUI:
iOS:
Android:
Sample Code:
(Android Native App)
public class AndroidTest {
public class AndroidTest {
private AppiumDriver driver;
@Before
public void setUp() throws Exception {
File classpathRoot = new
File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot,
"../../../apps/ApiDemos/bin");
File app = new File(appDir,
"ApiDemos-debug.apk");
DesiredCapabilities capabilities = new
DesiredCapabilities();
capabilities.setCapability("device","Android");
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability(CapabilityType.VERSION, "4.4");
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("app-package",
"com.example.android.apis");
capabilities.setCapability("app-activity",
".ApiDemos");
driver = new AppiumDriver(new
URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
@After
public void tearDown() throws Exception {
driver.quit();
}
@Test
public void apiDemo(){
WebElement el =
driver.findElement(By.name("Animation"));
assertEquals("Animation",
el.getText());
el = driver.findElementByClassName("android.widget.TextView");
assertEquals("API Demos",
el.getText());
el =
driver.findElement(By.name("App"));
el.click();
List<WebElement> els =
driver.findElementsByClassName("android.widget.TextView");
assertEquals("Activity",
els.get(2).getText());
}
(iOS Native App)
public class UICatalogTest {
public class UICatalogTest {
private
AppiumDriver driver;
private
WebElement row;
@Before
public void
setUp() throws Exception {
// set up
appium
File classpathRoot
= new File(System.getProperty("user.dir"));
File appDir
= new File(classpathRoot,
"../../../apps/UICatalog/build/Release-iphonesimulator");
File app =
new File(appDir, "UICatalog.app");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability(CapabilityType.VERSION, "7.1");
capabilities.setCapability(CapabilityType.PLATFORM, "Mac");
capabilities.setCapability("device", "iPhone
Simulator");
capabilities.setCapability("app", app.getAbsolutePath());
driver =
new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"),
capabilities);
}
@After
public void
tearDown() throws Exception {
driver.quit();
}
private void
openMenuPosition(int index) {
//populate
text fields with two random number
MobileElement table = new
MobileElement((RemoteWebElement)driver.findElementByClassName("UIATableView"),
driver);
row =
table.findElementsByClassName("UIATableCell").get(index);
row.click();
}
private Point
getCenter(WebElement element) {
Point
upperLeft = element.getLocation();
Dimension
dimensions = element.getSize();
return new
Point(upperLeft.getX() + dimensions.getWidth()/2, upperLeft.getY() +
dimensions.getHeight()/2);
}
@Test
public void
testFindElement() throws Exception {
//first
view in UICatalog is a table
MobileElement table = new MobileElement((RemoteWebElement)driver.findElementByClassName("UIATableView"),
driver);
assertNotNull(table);
//is number
of cells/rows inside table correct
List<WebElement> rows =
table.findElementsByClassName("UIATableCell");
assertEquals(12,
rows.size());
//is first
one about buttons
assertEquals("Buttons, Various uses of UIButton",
rows.get(0).getAttribute("name"));
//navigationBar is not inside table
WebElement
nav_bar = null;
try {
nav_bar =
table.findElementByClassName("UIANavigationBar");
} catch
(NoSuchElementException e) {
//expected
}
assertNull(nav_bar);
//there is
nav bar inside the app
driver.getPageSource();
nav_bar =
driver.findElementByClassName("UIANavigationBar");
assertNotNull(nav_bar);
}
@Test
public void
test_location() {
//get third
row location
row =
driver.findElementsByClassName("UIATableCell").get(2);
assertEquals(0,
row.getLocation().getX());
assertEquals(152, row.getLocation().getY());
}
@Test
public void
testScreenshot() {
//make
screenshot and get is as base64
WebDriver
augmentedDriver = new Augmenter().augment(driver);
String
screenshot = ((TakesScreenshot)
augmentedDriver).getScreenshotAs(OutputType.BASE64);
assertNotNull(screenshot);
//make
screenshot and save it to the local filesystem
File file =
((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
assertNotNull(file);
}
@Test
public void
testTextFieldEdit() {
//go to the
text fields section
openMenuPosition(2);
WebElement
text_field = driver.findElementsByClassName("UIATextField").get(0);
//get
default/empty text
String
default_val = text_field.getAttribute("value");
//write
some random text to element
String
rnd_string = RandomStringUtils.randomAlphanumeric(6);
text_field.sendKeys(rnd_string);
assertEquals(rnd_string, text_field.getAttribute("value"));
//send some
random keys
String
rnd_string2 = RandomStringUtils.randomAlphanumeric(6);
Actions
swipe = new Actions(driver).sendKeys(rnd_string2);
swipe.perform();
//check if
text is there
assertEquals(rnd_string + rnd_string2,
text_field.getAttribute("value"));
//clear
text_field.clear();
//check if
is empty/has default text
assertEquals(default_val, text_field.getAttribute("value"));
}
@Test
public void
testAlertInteraction() {
//go to the
alerts section
openMenuPosition(10);
//trigger
modal alert with cancel & ok buttons
List<WebElement> triggerOkCancel = driver.findElementsByAccessibilityId("Show
OK-Cancel");
triggerOkCancel.get(1).click();
Alert alert
= driver.switchTo().alert();
//check if
title of alert is correct
assertEquals("UIAlertView <Alert message>",
alert.getText());
alert.accept();
}
@Test
public void
testScroll() {
//scroll
menu
//get
initial third row location
row =
driver.findElementsByClassName("UIATableCell").get(2);
Point
location1 = row.getLocation();
Point center = getCenter(row);
//perform
swipe gesture
driver.swipe(center.getX(), center.getY(), center.getX(),
center.getY()-20, 1);
//get new
row coordinates
Point
location2 = row.getLocation();
assertEquals(location1.getX(), location2.getX());
assertNotSame(location1.getY(), location2.getY());
}
@Test
public void
testSlider() {
//go to
controls
openMenuPosition(1);
//get the
slider
WebElement
slider = driver.findElementByClassName("UIASlider");
assertEquals("50%", slider.getAttribute("value"));
Point
sliderLocation = getCenter(slider);
driver.swipe(sliderLocation.getX(), sliderLocation.getY(),
sliderLocation.getX()-100, sliderLocation.getY(), 1);
assertEquals("0%",
slider.getAttribute("value"));
}
@Test
public void
testSessions() throws Exception {
HttpGet
request = new HttpGet("http://localhost:4723/wd/hub/sessions");
HttpClient
httpClient = new DefaultHttpClient();
HttpResponse response =
httpClient.execute(request);
HttpEntity
entity = response.getEntity();
JSONObject
jsonObject = (JSONObject) new JSONParser().parse(EntityUtils.toString(entity));
String
sessionId = driver.getSessionId().toString();
assertEquals(jsonObject.get("sessionId"), sessionId);
}
@Test
public void
testSize() {
Dimension
table = driver.findElementByClassName("UIATableView").getSize();
Dimension
cell = driver.findElementsByClassName("UIATableCell").get(0).getSize();
assertEquals(table.getWidth(), cell.getWidth());
assertNotSame(table.getHeight(), cell.getHeight());
}
@Test
public void
testSource() {
//get main
view soruce
String
source_main = driver.getPageSource();
assertTrue(source_main.contains("UIATableView"));
assertTrue(source_main.contains("TextFields, Uses of
UITextField"));
//got to
text fields section
openMenuPosition(2);
String
source_textfields = driver.getPageSource();
assertTrue(source_textfields.contains("UIAStaticText"));
assertTrue(source_textfields.contains("TextFields"));
assertNotSame(source_main, source_textfields);
}
(Android Web App)
public class ChromeTest {
private WebDriver driver;
/**
* Instantiates the {@link #driver}
instance by using DesiredCapabilities which specify the
* 'iPhone Simulator' device and 'Chrome'
app.
* @throws Exception
*/
@Before
public void setUp() throws Exception {
DesiredCapabilities capabilities = new
DesiredCapabilities();
capabilities.setCapability("device", "Android");
capabilities.setCapability("platformName", "android");
capabilities.setCapability("version", "4.4");
capabilities.setCapability("browserName", "chrome");
driver = new RemoteWebDriver(new
URL("http://127.0.0.1:4723/wd/hub"),
capabilities);
//driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
/**
* Navigates to
http://saucelabs.com/test/guinea-pig and interacts with the browser.
*
* @throws Exception
*/
@Test
public void runTest() throws Exception {
driver.get("http://saucelabs.com/test/guinea-pig");
Thread.sleep(1000);
WebElement idElement =
driver.findElement(By.id("i_am_an_id"));
assertNotNull(idElement);
assertEquals("I am a div",
idElement.getText());
WebElement commentElement =
driver.findElement(By.id("comments"));
assertNotNull(commentElement);
commentElement.sendKeys("This is
an awesome comment");
WebElement submitElement =
driver.findElement(By.id("submit"));
assertNotNull(submitElement);
submitElement.click();
Thread.sleep(7000);
WebElement yourCommentsElement =
driver.findElement(By.id("your_comments"));
assertNotNull(yourCommentsElement);
assertTrue(driver.findElement(By.id("your_comments")).getText().contains("This
is an awesome comment"));
System.out.println(driver.getCurrentUrl());
}
/**
* Closes the {@link #driver} instance.
*
* @throws Exception
*/
@After
public void tearDown() throws Exception {
driver.quit();
}
}
(iOS Web App)
public class SafariTest {
private WebDriver driver;
/**
* Instantiates the {@link #driver}
instance by using DesiredCapabilities which specify the
* 'iPhone Simulator' device and 'safari'
app.
* @throws Exception
*/
@Before
public void setUp() throws Exception {
DesiredCapabilities capabilities = new
DesiredCapabilities();
capabilities.setCapability("device", "iPhone
Simulator");
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("version",
"7.1");
capabilities.setCapability("browserName", "safari");
driver = new RemoteWebDriver(new
URL("http://127.0.0.1:4723/wd/hub"),
capabilities);
//driver.manage().timeouts().implicitlyWait(30,
TimeUnit.SECONDS);
}
/**
* Navigates to
http://saucelabs.com/test/guinea-pig and interacts with the browser.
*
* @throws Exception
*/
@Test
public void runTest() throws Exception {
driver.get("http://saucelabs.com/test/guinea-pig");
Thread.sleep(1000);
WebElement idElement =
driver.findElement(By.id("i_am_an_id"));
assertNotNull(idElement);
assertEquals("I am a div",
idElement.getText());
WebElement commentElement =
driver.findElement(By.id("comments"));
assertNotNull(commentElement);
commentElement.sendKeys("This is
an awesome comment");
WebElement submitElement =
driver.findElement(By.id("submit"));
assertNotNull(submitElement);
submitElement.click();
Thread.sleep(7000);
WebElement yourCommentsElement =
driver.findElement(By.id("your_comments"));
assertNotNull(yourCommentsElement);
assertTrue(driver.findElement(By.id("your_comments")).getText().contains("This
is an awesome comment"));
System.out.println(driver.getCurrentUrl());
}
/**
* Closes the {@link #driver} instance.
*
* @throws Exception
*/
@After
public void tearDown() throws Exception {
driver.quit();
}
}
Advance Options: