Automating the Android calculator

We are going to write a basic automation script that will enable us to perform some sums with the build in Android calculator. The first thing we are going to do is configure BasePageObject that all future page objects can extend as we did in our Selenium framework:

package com.masteringselenium.page_objects;

import com.masteringselenium.AppiumBase;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.TouchAction;
import org.openqa.selenium.support.ui.WebDriverWait;

public abstract class BasePageObject {

AppiumDriver driver;
WebDriverWait webDriverWait;
TouchAction touchAction;

BasePageObject() {
try {
this.driver = AppiumBase.getDriver();
} catch (Exception ignored) {
//This will be be thrown when the test starts
//if it cannot connect to a RemoteWebDriver Instance
}

this
.webDriverWait = new WebDriverWait(driver, 30, 250);
this.touchAction = new TouchAction(driver);
}
}

This is going to provide an easy way for our page objects to get an AppiumDriver instance as well as giving us a couple of useful objects that will probably be used more than once, a WebDriverWait object and a TouchAction object. The next job is to create CalculatorPageObject, but to do this we are going to need a way to examine the calculator object on a device. To do that we will need to download the Appium desktop application which is available at https://github.com/appium/appium-desktop/releases. While you are doing that you will also want to install ADB, this will be useful to query the device you are using to get hold of package names. You can get ADB at https://developer.android.com/studio/command-line/adb.

Once you have got these packages installed, you are ready to start up Appium desktop, it will look like this:

First of all you will want to click on Start Server, which will provide you with this screen:

Next we want to click on the magnifying glass icon in the top left.  This will pop up a box that looks like this:

To start a debug session, we need to configure DesiredCapabilities. We can do this by generating a JSON representation of DesiredCapabilities. To do this, we now need to connect our Android device to our machine via a USB cable and find out which calculator package is installed. Samsung bundles their own calculator app so if you are not using a Samsung device you may find a different package.  

Don't forget to put your test device into development mode before trying to use ADB commands. If it isn't in the development mode, it will just ignore the commands. To turn it on you normally go to Settings | About phone | Build number and then tap on the build number seven times, different devices may have slightly different way to enable it though.

The command you need to type into your Terminal is:

adb shell pm list packages -f |grep calc

On a Samsung S6 it returns the following:

package:/system/priv-app/SecCalculator_N/SecCalculator_N.apk=com.sec.android.
app.popupcalculator

We are now ready to use this information to configure our DesiredCapabilities:

{
"platformName": "Android",
"deviceName": "Samsung S6",
"appPackage": "com.sec.android.app.popupcalculator",
"appActivity": ".Calculator"
}

We have an android device, so we are using platformName of Android. The deviceName can be anything, so I have used the name of the device we are connecting to. The appPackage is the one we found using our ADB command and the default appActivity for calculator apps in Android is .Calculator.  Copy the preceding into your JSON representation block and you should have something that looks like this:

Now click on Start Session and Appium will launch the Calculator app, and load a view of what you can see on your device in the  session window:  

You can now select elements on the screen and get locator information. We are going to use this to build up our page object:

Here is our CalculatorPageObject, if you are not using a Samsung device you may have slightly different locators, but generally the page object should look very similar:

package com.masteringselenium.page_objects;

import com.lazerycode.selenium.util.Query;
import io.appium.java_client.MobileBy;
import io.appium.java_client.touch.offset.ElementOption;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static io.appium.java_client.touch.TapOptions.tapOptions;

public class CalculatorPageObject extends BasePageObject {

private Query one = new Query(MobileBy.AccessibilityId("1"),
driver);
private Query two = new Query(MobileBy.AccessibilityId("2"),
driver);
private Query three = new Query(MobileBy.AccessibilityId("3"),
driver);
private Query four = new Query(MobileBy.AccessibilityId("4"),
driver);
private Query five = new Query(MobileBy.AccessibilityId("5"),
driver);
private Query six = new Query(MobileBy.AccessibilityId("6"),
driver);
private Query seven = new Query(MobileBy.AccessibilityId("7"),
driver);
private Query eight = new Query(MobileBy.AccessibilityId("8"),
driver);
private Query nine = new Query(MobileBy.AccessibilityId("9"),
driver);
private Query zero = new Query(MobileBy.AccessibilityId("0"),
driver);
private Query addButton = new
Query(MobileBy.AccessibilityId("Plus"), driver);
private Query subtractButton = new
Query(MobileBy.AccessibilityId("Minus"), driver);
private Query equalsButton = new
Query(MobileBy.AccessibilityId("Equal"), driver);
private Query result = new
Query(MobileBy.id("com.sec.android.app.popupcalculator:id
/txtCalc"
), driver);

private final Map<Character, Query> NUMBERS =
Collections.unmodifiableMap(
new HashMap<Character, Query>() {{
put('1', one);
put('2', two);
put('3', three);
put('4', four);
put('5', five);
put('6', six);
put('7', seven);
put('8', eight);
put('9', nine);
put('0', zero);
}});

public CalculatorPageObject enterNumber(String number) {
for (Character digit : number.toCharArray()) {
touchAction.tap(tapOptions()
.withElement(ElementOption.element(NUMBERS.
get(digit).findMobileElement()))).perform();
}

return this;
}

public CalculatorPageObject add() {
touchAction.tap(tapOptions().withElement
(ElementOption.element(addButton.findMobileElement())))
.perform();

return this;
}

public CalculatorPageObject subtract() {
touchAction.tap(tapOptions().withElement
(ElementOption.element(subtractButton.findMobileElement())))
.perform();

return this;
}

public String equals() {
touchAction.tap(tapOptions().withElement
(ElementOption.element(equalsButton.findMobileElement())))
.perform();

return result.findMobileElement().getText();
}

}

This is again fairly self explanatory. At the top, we have a series of Query elements that can be used to locate elements on the screen. Then we have a method that will take a number string and convert it into a series of tap events. Then we have some methods that will hit some individual buttons like plugin and minus. Finally, we have an equals method that will hit the equals button and then capture the value currently displayed on the screen.  If you are still in your inspector session at this point, you can quit and go back to the running Appium server, we are about to use to run a test.

Before we can run that test, however, we are going to need to write it, but that's very straightforward now that we have our page object. Here it is:

package com.masteringselenium.tests;

import com.masteringselenium.AppiumBase;
import com.masteringselenium.page_objects.CalculatorPageObject;
import io.appium.java_client.android.Activity;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class CalculatorIT extends AppiumBase {

@BeforeMethod
public void setCorrectActivity() throws Exception {
String appPackage = "com.sec.android.app.popupcalculator";
String appActivity = ".Calculator";
getDriver(new Activity(appPackage, appActivity));
}

@Test
public void AddNumbersTogether() {
CalculatorPageObject calculatorPageObject = new
CalculatorPageObject();

String result = calculatorPageObject.enterNumber("100")
.add()
.enterNumber("27")
.equals();

assertThat(result).isEqualTo("127");
}
}

We have two pieces to our test. First of all before we start running the test, we invoke the calculator activity in @BeforeMethod. We could do this inside the test as well, but the advantage of doing it outside the test is if we have multiple tests, we would want to run them inside the same activity.

Our test is then quite self explanatory. We enter a number, tap add, enter another number, and then tap equals. Finally, we compare the value that was returned after we tapped equals to make sure it matches our expectation.

Congratulations, you have just written your first Appium test.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.154.171