Appium
To learn how to run Appium Driver tests with Java in Perfecto, review the following information. If you are already familiar with Appium, check out our condensed Quick start: Run your first Appium test with Perfecto article instead.
To learn about Appium 2, including how to use an Appium 2-compliant client with Perfecto, see also our free Appium 2.0: Fundamentals course on the Perfecto Education site. To register for this course, you must be logged in. For upgrade information, see Upgrade to an Appium 2-compliant client.
The following setup information is based on a sample project available on GitHub, created to help you get up and running with Appium and Perfecto. The project is a working example that demonstrates how to configure and run Appium tests in a Perfecto environment, making it easier to understand the setup and adapt it to your own use cases.
desiredCapabilities
format to support teams transitioning from Appium 1. For teams adopting Appium 2 from scratch, consider exploring the options
-based syntax to align with the W3C WebDriver specification. For guidance on adopting this approach, see the official Appium 2 documentation.
To run a Java Appium script in Perfecto, you should:
- Be familiar with Appium
- Have existing tests to work with
- Be a novice user of Perfecto
The setup process involves modifying your existing scripts to include:
- What driver you want to use
- Where your Perfecto instance is located
- Who you are
- What devices you want to work on
On this page:
Prerequisites
Before you get started, make sure you have installed the following:
-
Java 11
-
An IDE of your choice, such as Eclipse or IntelliJ IDEA (consider using IntelliJ IDEA for a better Appium and Maven integration)
Additional setup per IDE
If you use Eclipse with the following:
-
Apache Maven as a dependency management tool: Install the Maven plugin
-
TestNG: Install the TestNG plugin
If you use IntelliJ IDEA with Apache Maven, install the Maven plugin for IDEA. IntelliJ IDEA versions 7 and later include the TestNG plugin as a built-in plugin.
Optional installations
For source control management, you can install git.
This plugin is usually bundled with the IDE, but ensure it is enabled.
Appium limitations
Perfecto is aligned with Appium and, therefore, does not support using the clipboard for copy-paste operations on real devices.
For reference, see the Appium information for the custom command extensions mobile: setPasteboard and mobile: getPasteboard.
1 | Get started
- Access the sample project in GitHub and copy the clone URL.
- Open your IDE and check out the project from GitHub.
2 | Configure the script for Perfecto
In this step, we update the pom.xml
file with the required Perfecto dependencies and add in security information, the Perfecto cloud name, Smart Reporting information, and test data. We also want to make sure that the script exits gracefully.
The updated TestNG script is called PerfectoAppium.java
. The following procedure walks you through the configuration. The script can be used with any Java-based testing framework.
The script uses a sample application that is in the lib
of the project:
You can choose to skip this and immediately start using your own application by adding the application manually to the Perfecto repository and then referencing it in the code. To learn how to upload an item to the repository, see Manage the repository (for upload via the Perfecto UI) or Upload Item to Repository (for upload via the Perfecto REST API).
Expand a step to view its content.

Copy the dependencies in the pom.xml
file and paste them into the pom.xml
file of your own project. This step is essential because the imports in our final script only work when the dependencies specified in this file are available.

Our sample project uses the PerfectoLabUtils.getSecurityToken()
method to securely retrieve the Perfecto security token at runtime. To see this code in context, see PerfectoAppium.java.
In your own project, provide the security token in one of the following ways.
This method looks for the token under the key perfecto.security.token
, using the utility class ApplicationPropertiesUtil
.
-
In an
application.properties
file (in the project root or classpath):Copyperfecto.security.token=<<SECURITY TOKEN>>
-
As a JVM system property, typically passed via Maven:
Copymvn test -Dperfecto.security.token=<<SECURITY TOKEN>>
-
As an environment variable, if supported by
ApplicationPropertiesUtil
in the project setup.
For help generating a token, see Generate a security token.

Use capabilities to select a device from the Perfecto lab. You can be as generic or specific as needed. In our script, we have included the capabilities shown in the following code snippet:
browserName
: The name of the browsermodel
: The device modelenableAppiumBehavior
: Set totrue
to ensure compatibility with standard Appium behavioropenDeviceTimeout
: The timeout, in minutes, to wait for a specific device in case it is not available at the start of the script (use with caution)app
: The Perfecto repository path of the app under testappPackage
: The unique identifier of the Android app you want to run
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("perfecto:browserName", browserName);
capabilities.setCapability("perfecto:model", "Galaxy S.*|LG.*");
capabilities.setCapability("perfecto:enableAppiumBehavior", true);
capabilities.setCapability("perfecto:openDeviceTimeout", 2);
capabilities.setCapability("perfecto:app", repositoryKey); // Set Perfecto Media repository path of App under test.
capabilities.setCapability("perfecto:appPackage", "io.perfecto.expense.tracker"); // Set the unique identifier of your app
For more information on capabilities, see:

As part of creating an instance of the RemoteWebDriver, you need to supply the URL of your Perfecto cloud, for example, demo
or yourcompany
.
Our sample project uses the String cloudName = PerfectoLabUtils.getPerfectoCloudName();
method to securely retrieve the Perfecto cloud name at runtime. To see this code in context, see PerfectoAppium.java.
In your own project, provide your cloud URL in one of the following ways:
-
By adding the following line to your
application.properties
file. Replace <<CLOUD NAME>> with your actual cloud name.Copyperfecto.cloud.name=<<CLOUD NAME>>
-
If you're running your test using Maven, by adding the following line as a system property. This overrides any value set in
application.properties
.Copymvn test -Dperfecto.cloud.name=demo
Later in the test script, the cloud name is used to build the URL and create the driver, as shown in the following code snippet.
driver = new AndroidDriver(
new URL("https://" + cloudName + ".perfectomobile.com/nexperience/perfectomobile/wd/hub"),
capabilities);
This line:
-
Constructs the Appium server URL dynamically using the cloud name.
-
Creates a new instance of the
AndroidDriver
, which runs your test on a device in the Perfecto cloud.
For example, if the cloud name is demo
, the driver connects to: https://demo.perfectomobile.com/nexperience/perfectomobile/wd/hub

To get the most out of running your test in Perfecto, create an instance of the Smart Reporting client (ReportiumClient
). This will allow you to later retrieve and analyze the test report. The reporting client is responsible for gathering basic information about the test and transmitting it to Perfecto Smart Reporting.
In PerfectoLabUtils.java, the setReportiumClient()
constructs a ReportiumClient using RemoteWebDriver and metadata (job, project, tags) from property files. It centralizes the reporting client setup for reuse across tests.
public static ReportiumClient setReportiumClient(RemoteWebDriver driver, ReportiumClient reportiumClient)
throws Exception {
// Reporting client. For more details, see
// https://developers.perfectomobile.com/display/PD/Java
PerfectoExecutionContextBuilder perfectoExecutionContextBuilder = new PerfectoExecutionContext.PerfectoExecutionContextBuilder();
String jobName = ApplicationPropertiesUtil.getProperty("reportium.job.name");
if (null == driver) {
throw new Exception("Set Report Client : Driver can't be null");
}
perfectoExecutionContextBuilder = perfectoExecutionContextBuilder.withWebDriver(driver);
if (null != jobName) {
int jobNumber = 0;
String jobNumberStr = ApplicationPropertiesUtil.getProperty("reportium.job.number");
if (null == null) {
jobNumber = Integer.parseInt(jobNumberStr);
}
Job jobReference = new Job(jobName, jobNumber);
perfectoExecutionContextBuilder = perfectoExecutionContextBuilder.withJob(jobReference);
}
String projectName = ApplicationPropertiesUtil.getProperty("reportium.project.name");
if (null != projectName) {
String projectNumber = ApplicationPropertiesUtil.getProperty("reportium.project.number");
if (null == projectNumber) {
projectNumber = "1.0";
}
Project project = new Project(projectName, projectNumber);
perfectoExecutionContextBuilder = perfectoExecutionContextBuilder.withProject(project);
}
String tags = ApplicationPropertiesUtil.getProperty("reportium.tags");
if (tags != null) {
List<String> tagsList = Arrays.asList(tags.split(","));
perfectoExecutionContextBuilder = perfectoExecutionContextBuilder.withContextTags(tagsList);
}
PerfectoExecutionContext perfectoExecutionContext = perfectoExecutionContextBuilder.build();
reportiumClient = new ReportiumClientFactory().createPerfectoReportiumClient(perfectoExecutionContext);
if (reportiumClient == null) {
throw new Exception("Reportium client not created!");
}
return reportiumClient;
What you need to do:
-
Ensure the
WebDriver
instance is not nullThe method throws an exception if the passed
RemoteWebDriver driver
is null. Call this method after the driver has been initialized. -
Configure reporting properties
The method relies on several properties being defined. These must be present in the
application.properties
file or another supported source (for example, system properties ifApplicationPropertiesUtil is
configured to pull from them).Supply the following optional properties:
-
reportium.job.name
: The name of the job (for example, test suite or build) -
reportium.job.number
: The job/build number (should be an integer) -
reportium.project.name
: The name of the project -
reportium.project.number
: The project version or number -
reportium.tags
: Comma-separated tags (for example, smoke,regression)Tags are used as a freestyle text for filtering the reports in the Reporting app.
-
-
Update the
application.properties
file to include the relevant information. For example:Copyreportium.job.name=MyJob
reportium.job.number=123
reportium.project.name=MyProject
reportium.project.number=1.0
reportium.tags=smoke,regressionIf you don't set these properties, the client is still created, but job/project/tag info will be missing from reports.

Replace the sample test code in the main
method with the following code, which demonstrates a login scenario in an Android app using Reportium steps and waits for UI interactions such as entering email, password, and confirming successful login.
In our example, the test is separated into logical groupings of actions as logical steps. Each step is labeled and appears in the execution report together with the component actions. The beginning of each logical step is indicated with the stepStart()
method, providing the label of the step, and the end of each logical step with the stepEnd()
method (for the report).
reportiumClient = PerfectoLabUtils.setReportiumClient(driver, reportiumClient); // Creates reportiumClient
reportiumClient.testStart("Android Java Native Sample", new TestContext("tag2", "tag3")); // Starts the
// reportium test
reportiumClient.stepStart("Enter email");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
WebElement email = wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("login_email"))));
email.sendKeys("test@perfecto.com");
reportiumClient.stepEnd();
reportiumClient.stepStart("Enter password");
WebElement password = wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("login_password"))));
password.sendKeys("test123");
reportiumClient.stepEnd();
reportiumClient.stepStart("Click login");
WebElement login = wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("login_login_btn"))));
login.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Login Successful");
wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.id("list_add_btn"))));
reportiumClient.stepEnd();

To close Smart Reporting and the driver, supply an indication of the final outcome of the test by generating a TestResult
instance in an @AfterMethod
.
@AfterMethod
public void afterMethod(ITestResult result) {
TestResult testResult = null;
if (result.getStatus() == ITestResult.SUCCESS) {
testResult = TestResultFactory.createSuccess();
} else if (result.getStatus() == ITestResult.FAILURE) {
testResult = TestResultFactory.createFailure(result.getThrowable());
}
if(null != reportiumClient) {
reportiumClient.testStop(testResult);
// Retrieve the URL to the DigitalZoom Report
String reportURL = reportiumClient.getReportUrl();
System.out.println(reportURL);
}
if(null != driver) {
driver.quit();
}
}
In our example, the createSuccess
method notifies the reporting server that the test resulted in a successful status. The createFailure
method notifies the reporting server that the test resulted in an unsuccessful status and supports adding a notification message that is displayed in the test report. Our script also provides a failure reason, but this is optional. To learn more about failure reasons in reporting, see Work with failure reasons.
Last, make sure to close and quit the RemoteWebDriver
and retrieve the Smart Reporting URL for the generated test report.
Also in this section