- automated testing
- mobile application software (App) testing
- distributed test execution (Appium server)
- Java
- JDK 1.8.0_121 (32 bit, 64 bit)
- Selenium 3.4.0
- Appium Java-Client 5.0.0-BETA8
- Appium Desktop 1.1.0-beta.1
- TestNG 6.11
- Calculator 4.4.2 (Android system app)
- Android 4.4.2
- Eclipse Neon
- Maven 3.5.0
- Windows 10 (64 bit)
- Java Application
- TestNG Suite
- Maven build
The third party software files are not part of this project's file repository. However, the project's setup contains notations of paths and file names of that software to be used for the project setup. With the help of these notations, after obtaining the files, a project user can place them in the respective directories.
The file directories are set up in a way to facilitate the use of Maven.
Within the "resources" directory there are two subdirectories:
- "int"
"int" stands for "internal". This directory contains all the files whose content is customized by the project user and which are therefore related to the internal setup of the project.
This projects java implementations contain a number of files serving as utilities for common tasks that are not explicitly related to the specific test scope. Therefore, in this documentation, these files are only described more in detail if relevant for the understanding of the test topic.
The project comprehends one single test case.
- start Calculator app
- enter mathematical equation
- let equation result be calculated
- retrieve equation result from app
- execute test assert
Variables:
A
: computed equation resultX
: expected equation result
Assert:
Computed equation result A
is equal to expected equation result X
.
The concrete test assert implementation is given in a different segment of this documentation.
The project contains one single test class CalculateEquationResultTestCase
which again contains one single test method testCalculateResultOfEquation
.
CalculateEquationResultTestCase
contains test data:
- expected equation result
X
for assert
String _ExpectedEquationResult=
"2"
The variable _ExpectedEquationResult
is of data type String
. This allows the test to be adapted for other test cases that expect a non-numerical equation result, i.e. when testing for division by zero.
The beforeMethod
takes care of instantiating a AndroidDriverManagerFactory
which is used to retrieve a AndroidDriver
instance.
_AndroidDriverManager=
_AndroidDriverManagerFactory.createAndroidDriverManager();
if(_AndroidDriverManager!=null)
{
_AndroidDriver=
_AndroidDriverManager.createAndroidDriver();
}
The test method testCalculateResultOfEquation
manages the realization of the test sequence.
First, the equation gets entered. Then the result is being calculated and retrieved.
_ComputedEquationResult=
new CalculatorPage(
_AndroidDriver).calculateResultForEquation1Plus1();
The variable _ComputedEquationResult
is of data type String
for the same reasons as the variable _ExpectedEquationResult
, which are described in a different segment of this documentation.
In the end the assertion is called. A specific error message is set for when an assertion error gets thrown.
Assert.assertTrue(
isComputedEquationResultEqualToExpectedEquationResult(),
"Expected result: " +
_ExpectedEquationResult +
"\n" +
"Computed result: " +
_ComputedEquationResult);
The auxiliary method isComputedEquationResultEqualToExpectedEquationResult
determines if the computed equation result is equal to the expected equation result. This value gets used by the assert.
The afterMethod
takes care of closing the Calculator app.
Browser Executable and AndroidDriver
handling in this project happens in a three level system.
AndroidDriverManagerFactory
AndroidDriverManager
- Appium server
The AndroidDriverManagerFactory
instantiates the AndroidDriverManager
.
This project setup works on the basis of distributed test execution, based on a Appium server. The project setup contains a server environment working on a single computer - i.e. without a physical server architecture. The Appium server and the mobile device are being run and connected on the localhost. This setup is supposed to demonstrate how distributed test execution is implemented under Appium server. The project's scope in this regard is mainly on the actual test execution setup. Other server related topics, like network settings, are not within that scope.
Before any 'AndroidDriver' can be instantiated, the Appium server and the mobile device must be up and running. The mobile device needs to be connected to the Appium server.
Appium Server
The Appium server is started by executing the Appium desktop application and following the steps indicated there.
Mobile Device
A mobile device needs to be running and be available for the Appium server. Setting up and connecting the device to the server can be achieved in a variety of different ways. The mobile device setup is not within the scope of this documentation.
Instantiation of the AndroidDriver
is handled in AndroidDriverManager
.
The AndroidDriverManager
class sets values in the DesiredCapabilities
. The DesiredCapabilities
set here can be grouped into three categories:
- device specification
- mobile operating system specification
- app specification
_DesiredCapabilities=
new DesiredCapabilities();
//Device specification
_DesiredCapabilities.setCapability(
"udid",
"emulator-5554");
_DesiredCapabilities.setCapability(
"deviceName",
".");
//Mobile operating system specification
_DesiredCapabilities.setCapability(
"platformName",
"Android");
_DesiredCapabilities.setCapability(
"platformVersion",
"4.4");
//App specification
_DesiredCapabilities.setCapability(
"appPackage",
"com.android.calculator2");
_DesiredCapabilities.setCapability(
"appActivity",
".Calculator");
The device specification serves the purpose of identifying the mobile device to be used for the test in case there is more than one mobile device connected to the Appium server. The identification is achieved by setting the DesiredCapabilities
capability udid
. The capability deviceName
is not necessary for identifying the device. However, if this capability is not getting set, the Appium server throws an error when executing the test. Therefore, the capability deviceName
must be set. The concrete value assigned to it here is not considered by the Appium server. An arbitrary value can be chosen.
The AndroidDriver
's constructor takes the URL of the Appium server and the DesiredCapabilities
as arguments.
_AndroidDriver=
new AndroidDriver<WebElement>(
new URL(
"http://127.0.0.1:4723/wd/hub"),
_DesiredCapabilities);
Following are the details of the app automation parts of this project's specific test case described in a different segment of this documentation.
The test case covers one user interface:
- Calculator main screen
For implementation of the CalculatorPage
class the page object pattern was applied.
PageObject
is an abstract class implementing common behaviour of all [...]Page
classes.
The CalculatorPage
class represents the Calculator app main screen. Following are the web elements relevant to the test case:
- digit "1" button
- "plus" sign button
- "equals" sign button
- equation text field
@FindBy(
id=
"digit1")
private WebElement _Digit1Button;
@FindBy(
id=
"plus")
private WebElement _PlusSignButton;
@FindBy(
id=
"equal")
private WebElement _EqualsSignButton;
@FindBy(
xpath=
"//*[@resource-id='com.android.calculator2:id/display']/android.widget.EditText")
private WebElement _EquationTextField;
The test sequence is executed by the beforeMethod
and testCalculateResultOfEquation
methods of the CalculateEquationResultTestCase
class. Following are the test sequence parts concerning app automation.
beforeMethod
_AndroidDriver=
_AndroidDriverManager.createAndroidDriver();
testCalculateResultOfEquation
_ComputedEquationResult=
new CalculatorPage(
_AndroidDriver).calculateResultForEquation1Plus1();
The Calculator app is getting started by instantiating the AndroidDriver
in the AndroidDriverManager
class.
_AndroidDriver=
_AndroidDriverManager.createAndroidDriver();
The implementation for instantiating the AndroidDriver
is shown in a different segment of this documentation.
_ComputedEquationResult=
new CalculatorPage(
_AndroidDriver).calculateResultForEquation1Plus1();
First the buttons for digit "1", "plus", again digit "1" and finally "equals" symbol are clicked in order. The computed result is retrieved from the calculators equation text field. The sequence of these steps is defined in the CalculatorPage
class.
public String calculateResultForEquation1Plus1()
{
return clickDigit1Button().clickPlusSignButton().clickDigit1Button().clickEqualsSignButton().getEquationTextFieldText();
}
The concrete actions are implemented in the WebElementActions
class.
public static void click(
WebElement webElement)
{
if(webElement!=null)
{
webElement.click();
}
}
public static String getText(
WebElement webElement)
{
String text=
null;
if(webElement!=null)
{
text=
webElement.getText();
}
return text;
}
The test assert is executed by the testCalculateResultOfEquation
method of the CalculateEquationResultTestCase
class.
The test assert textual phrasing is given in a different segment of this documentation.
The assert states that the computed equation result A
is equal to expected equation result X
.
The value of X
is set in the CalculateEquationResultTestCase
class as _ExpectedEquationResult
.
The boolean value indicating whether or not the the computed equation result is equal to the expected equation result needs to be retrieved for the assert. This is done by the auxiliary method isComputedEquationResultEqualToExpectedEquationResult
.
Assert.assertTrue(
isComputedEquationResultEqualToExpectedEquationResult(),
"Expected result: " +
_ExpectedEquationResult +
"\n" +
"Computed result: " +
_ComputedEquationResult);
For convenience the project contains the runnable java class Launcher
. Its purpose is to initiate test execution directly from a java application.
Test execution is prepared by instantiating a TestNG
object and setting the CalculateEquationResultTestCase.xml
TestNG XML as the reference file for the test. Test execution is then started by calling the TestNG
run
method.
TestNG testNG=
new TestNG();
List<String> suiteList=
Lists.newArrayList();
suiteList.add(
PathRetrieve.retrieveAbsolutePathStringFromRelativePathString(
this,
"/int/testng/xml/CalculateEquationResultTestCase.xml"));
testNG.setTestSuites(
suiteList);
testNG.run();
Additionally user information about the application status is displayed.
InfoAlert infoAlert=
new InfoAlert();
infoAlert.createAlert(
"Executing Test[...]");
[...]
infoAlert.closeAlert();
infoAlert.createAlert(
"Showing Test Results[...]");
[...]
infoAlert.closeAlert();
After test execution the test results are being opened in a browser window.
BrowserShowFile.showFileInBrowser(
".\\test-output\\emailable-report.html");
CalculateEquationResultTestCase.xml
is the TestNG XML file which can be run directly.
The projects directory structure is suited to be used with a Maven build. pom.xml
is the respective Maven XML file. The Maven build can be used to compile the source, copy the resources and run the test by using the Maven goal test
.