1 | Select a framework and scripting language
With Appium, Perfecto supports several scripting languages. To get started, do the following:
- Expand the language to work with.
- Review the prerequisites and perform any required steps.
- Download the project
.zip
file and extract it on your machine. You will modify the included test script in subsequent steps.
What language do you want to work with?

Prerequisites
Make sure you have installed the following items on your machine:
Download and extract the project
Perform the following steps to extract the project, download it to your machine, and navigate to the Java folder.
To download and extract the project:
-
Download the project.
-
Extract the project to your machine.
-
Inside the extracted project, navigate to Appium > Native > Java.
View the test script
The following code snippet shows the content of the included test script, PerfectoNativeSample.java
.

package ios;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import com.perfecto.reportium.client.ReportiumClient;
import com.perfecto.reportium.client.ReportiumClientFactory;
import com.perfecto.reportium.model.PerfectoExecutionContext;
import com.perfecto.reportium.model.Project;
import com.perfecto.reportium.test.TestContext;
import com.perfecto.reportium.test.result.TestResultFactory;
import com.perfecto.reportium.model.Job;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.IOSElement;
public class PerfectoNativeSample {
public static void main(String[] args) throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities("", "", Platform.ANY);
// 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the
// cloud name of demo.perfectomobile.com).
String cloudName = "<<cloud name>>";
// 2. Replace <<security token>> with your perfecto security token.
String securityToken = "<<security token>>";
capabilities.setCapability("securityToken", securityToken);
// 3. Set device capabilities.
capabilities.setCapability("platformName", "iOS");
capabilities.setCapability("model", "iPhone.*");
// 4. Set Perfecto Media repository path of App under test.
capabilities.setCapability("app", "PUBLIC:ExpenseTracker/Native/iOS/InvoiceApp1.0.ipa");
// 5. Set the unique identifier of your app
capabilities.setCapability("bundleId", "io.perfecto.expense.tracker");
// Set other capabilities.
capabilities.setCapability("enableAppiumBehavior", true);
capabilities.setCapability("autoLaunch", true); // Whether to install and launch the app automatically.
capabilities.setCapability("iOSResign",true); // Resign with developer certificate
// capabilities.setCapability("fullReset", false); // Reset app state by uninstalling app.
capabilities.setCapability("takesScreenshot", false);
capabilities.setCapability("screenshotOnError", true);
capabilities.setCapability("openDeviceTimeout", 5);
// Initialize the IOSDriver driver
IOSDriver<IOSElement> driver = new IOSDriver<IOSElement>(
new URL("https://" + cloudName + ".perfectomobile.com/nexperience/perfectomobile/wd/hub"),
capabilities);
// Setting implicit wait
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
PerfectoExecutionContext perfectoExecutionContext;
if (System.getProperty("jobName") != null) {
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("My Project", "1.0"))
.withJob(new Job(System.getProperty("jobName"),
Integer.parseInt(System.getProperty("jobNumber"))))
.withWebDriver(driver).build();
} else {
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("My Project", "1.0"))
.withWebDriver(driver).build();
}
ReportiumClient reportiumClient = new ReportiumClientFactory()
.createPerfectoReportiumClient(perfectoExecutionContext);
reportiumClient.testStart("Native Java iOS Sample", new TestContext("native", "ios"));
try {
// Sample test
reportiumClient.stepStart("Enter email");
WebDriverWait wait = new WebDriverWait(driver, 30);
IOSElement email = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("login_email"))));
email.sendKeys("test@perfecto.com");
reportiumClient.stepEnd();
reportiumClient.stepStart("Enter password");
IOSElement password = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("login_password"))));
password.sendKeys("test123");
reportiumClient.stepEnd();
reportiumClient.stepStart("Click login");
driver.hideKeyboard();
IOSElement login = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("login_login_btn"))));
login.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Add expense");
IOSElement add_expense = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("list_add_btn"))));
add_expense.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Select head");
IOSElement head = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("edit_head"))));
head.click();
List<WebElement> picker = wait
.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath("//*[@value=\"- Select -\"]")));
picker.get(0).sendKeys("Flight");
reportiumClient.stepEnd();
reportiumClient.stepStart("Enter amount");
IOSElement amount = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("edit_amount"))));
amount.sendKeys("100");
reportiumClient.stepEnd();
reportiumClient.stepStart("Save expense");
IOSElement save_expense = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name("add_save_btn"))));
save_expense.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Verify alert");
String expectedText = "Please enter valid category";
IOSElement alert = (IOSElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.name(expectedText))));
reportiumClient.reportiumAssert(expectedText, alert.getText().equalsIgnoreCase(expectedText));
reportiumClient.stepEnd();
reportiumClient.testStop(TestResultFactory.createSuccess());
} catch (Exception e) {
reportiumClient.testStop(TestResultFactory.createFailure(e));
assert (false);
}
// Prints the Smart Reporting URL
String reportURL = reportiumClient.getReportUrl();
System.out.println("Report url - " + reportURL);
// Quits the driver
driver.quit();
}
}

package android;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.Platform;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import com.perfecto.reportium.client.ReportiumClient;
import com.perfecto.reportium.client.ReportiumClientFactory;
import com.perfecto.reportium.model.PerfectoExecutionContext;
import com.perfecto.reportium.model.Project;
import com.perfecto.reportium.model.Job;
import com.perfecto.reportium.test.TestContext;
import com.perfecto.reportium.test.result.TestResultFactory;
import org.openqa.selenium.By;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
public class PerfectoNativeSample {
public static void main(String[] args) throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities("", "", Platform.ANY);
// 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the
// cloudName of demo.perfectomobile.com).
String cloudName = "<<cloud name>>";
// 2. Replace <<security token>> with your perfecto security token.
String securityToken = "<<security token>>";
capabilities.setCapability("securityToken", securityToken);
// 3. Set device capabilities.
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("model", "Galaxy S.*|LG.*");
// 4. Set Perfecto Media repository path of App under test.
capabilities.setCapability("app", "PUBLIC:ExpenseTracker/Native/android/ExpenseAppVer1.0.apk");
// 5. Set the unique identifier of your app
capabilities.setCapability("appPackage", "io.perfecto.expense.tracker");
// Set other capabilities.
capabilities.setCapability("enableAppiumBehavior", true); // Enable new Appium Architecture
capabilities.setCapability("autoLaunch", true); // Whether to install and launch the app automatically.
// capabilities.setCapability("fullReset", false); // Reset app state by uninstalling app.
capabilities.setCapability("takesScreenshot", false);
capabilities.setCapability("screenshotOnError", true);
capabilities.setCapability("openDeviceTimeout", 5);
// Initialize the AndroidDriver driver
AndroidDriver<AndroidElement> driver = new AndroidDriver<AndroidElement>(
new URL("https://" + cloudName.replace(".perfectomobile.com", "")
+ ".perfectomobile.com/nexperience/perfectomobile/wd/hub"),
capabilities);
// Setting implicit wait
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
PerfectoExecutionContext perfectoExecutionContext;
if (System.getProperty("jobName") != null) {
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("My Project", "1.0"))
.withJob(new Job(System.getProperty("jobName"),
Integer.parseInt(System.getProperty("jobNumber"))))
.withWebDriver(driver).build();
} else {
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.withProject(new Project("My Project", "1.0"))
.withWebDriver(driver).build();
}
ReportiumClient reportiumClient = new ReportiumClientFactory()
.createPerfectoReportiumClient(perfectoExecutionContext);
reportiumClient.testStart("Native Java Android Sample", new TestContext("native", "android"));
try {
// Sample test
reportiumClient.stepStart("Enter email");
WebDriverWait wait = new WebDriverWait(driver, 30);
AndroidElement email = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("login_email"))));
email.sendKeys("test@perfecto.com");
reportiumClient.stepEnd();
reportiumClient.stepStart("Enter password");
AndroidElement password = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("login_password"))));
password.sendKeys("test123");
reportiumClient.stepEnd();
reportiumClient.stepStart("Click login");
driver.hideKeyboard();
AndroidElement login = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("login_login_btn"))));
login.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Add expense");
AndroidElement add_expense = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("list_add_btn"))));
add_expense.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Select head");
AndroidElement head = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("input_layout_head"))));
head.click();
AndroidElement flight_option = (AndroidElement) wait
.until(ExpectedConditions.elementToBeClickable(driver.findElementByXPath("//*[@text=\"Flight\"]")));
flight_option.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Enter amount");
AndroidElement amount = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("add_amount"))));
amount.sendKeys("100");
reportiumClient.stepEnd();
reportiumClient.stepStart("Save expense");
AndroidElement save_expense = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElement(By.id("layout_buttons"))));
save_expense.click();
reportiumClient.stepEnd();
reportiumClient.stepStart("Verify alert");
String expectedText = "Select Currency";
AndroidElement alert = (AndroidElement) wait.until(ExpectedConditions.elementToBeClickable(
driver.findElementByXPath("//*[ @text='" + expectedText + "']")));
reportiumClient.reportiumAssert(expectedText, alert.getText().equalsIgnoreCase(expectedText));
reportiumClient.stepEnd();
reportiumClient.testStop(TestResultFactory.createSuccess());
} catch (Exception e) {
reportiumClient.testStop(TestResultFactory.createFailure(e));
}
// Prints the Smart Reporting URL
String reportURL = reportiumClient.getReportUrl();
System.out.println("Report url - " + reportURL);
// Quits the driver
driver.quit();
}
}

Prerequisites
Make sure you have installed:
-
The latest version of Node.js 14.x appropriate for your platform
On Windows 7, the latest version of Node.js 12.x is required. Newer versions are not supported.
Download and extract the project
Perform the following steps to extract the project, download it to your machine, and navigate to the Javascript folder.
To download and extract the project:
-
Download the project.
-
Extract the project to your machine.
-
Inside the extracted project, navigate to Appium > Native > Javascript.
Install node dependencies
Make sure you have installed node dependencies.
To install node dependencies:
-
Open a command line window and navigate to the wdio folder.
-
Run the following command:
Copynpm install
View the test script
The following code snippet shows the content of the included test script, native.js
. This script includes the test steps. The configuration is located in a dedicated configuration file.

describe('Native NodeJS', function() {
it('iOS Sample', async () => {
await browser.reportingClient.stepStart('Enter email');
var email = $('[name="login_email"]');
await email.waitForDisplayed({ timeout: 30000 });
await email.click()
await email.addValue("test@perfecto.com");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Enter password');
var password = $('[name="login_password"]');
await password.waitForDisplayed({ timeout: 30000 });
await password.click();
await password.addValue("test123");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Click login');
await driver.hideKeyboard();
var login = $('[name="login_login_btn"]');
await login.waitForDisplayed({ timeout: 30000 });
await login.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Add expense');
var add = $('[name="list_add_btn"]');
await add.waitForDisplayed({ timeout: 30000 });
await add.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Select head');
var head = $('[name="edit_head"]');
await head.waitForDisplayed({ timeout: 30000 });
await head.click();
var flight = $("//*[@value='- Select -']");
await flight.waitForDisplayed({ timeout: 30000 });
await flight.click();
await flight.addValue("Flight");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Enter amount');
var add = $('[name="edit_amount"]');
await add.waitForDisplayed({ timeout: 30000 });
await add.click();
await add.addValue("100");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Save expense');
var layout = $('[name="add_save_btn"]');
await layout.waitForDisplayed({ timeout: 30000 });
await layout.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart("Verify alert");
const expectedText = "Please enter valid category"
var alert = $('[name="' + expectedText + '"]');
await alert.waitForDisplayed({ timeout: 30000 });
var result = await alert.getText();
await browser.reportingClient.reportiumAssert(expectedText, result == expectedText);
});
});

describe('Native NodeJS', function () {
it('Android Sample', async () => {
await browser.reportingClient.stepStart('Enter email');
var email =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/login_email")');
await email.waitForDisplayed({ timeout: 30000 });
await email.addValue("test@perfecto.com");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Enter password');
var password =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/login_password")');
await password.waitForDisplayed({ timeout: 30000 });
await password.addValue("test123");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Click login');
await driver.hideKeyboard();
var login =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/login_login_btn")');
await login.waitForDisplayed({ timeout: 30000 });
await login.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Add expense')
var add =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/list_add_btn")');
await add.waitForDisplayed({ timeout: 30000 });
await add.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Select head')
var head =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/input_layout_head")');
await head.waitForDisplayed({ timeout: 30000 });
await head.click();
var flight =
$('//*[@text="Flight"]');
await flight.waitForDisplayed({ timeout: 30000 });
await flight.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Enter amount')
var add =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/add_amount")');
await add.waitForDisplayed({ timeout: 30000 });
await add.addValue("100");
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart('Save expense')
var layout =
$('android=new UiSelector().resourceId("io.perfecto.expense.tracker:id/layout_buttons")');
await layout.waitForDisplayed({ timeout: 30000 });
await layout.click();
await browser.reportingClient.stepEnd();
await browser.reportingClient.stepStart("Verify alert");
const expectedText = "Select Currency"
var alert =
$('//*[@text="' + expectedText + '"]');
await alert.waitForDisplayed({ timeout: 30000 });
var result = await alert.getText();
await browser.reportingClient.reportiumAssert(expectedText, result == expectedText);
});
});
View the test configuration file
For NodeJS, the configuration is available in a dedicated configuration file called conf.js
. The following code snippet shows the content of this file.

const path = require('path');
const Reporting = require('perfecto-reporting');
var reportingClient;
//1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
var host = '<<cloud name>>';
// 2. Replace <<security token>> with your perfecto security token.
var securityToken = '<<security token>>';
host = process.env.HOST == null ? host : process.env.HOST;
securityToken = process.env.SECURITY_TOKEN == null ? securityToken : process.env.SECURITY_TOKEN;
//Define your global tags here:
const tags = ['SampleTag1'];
global.STEP_TIMEOUT = 900000;
global.IMPLICIT_TIMEOUT = 5000;
exports.config = {
securityToken: securityToken,
protocol: 'http',
hostname: host + '.perfectomobile.com',
path: '/nexperience/perfectomobile/wd/hub',
port: 80,
sync: true,
bail: 0,
exclude: [],
specs: [
'ios/native.js'
],
maxInstances: 1,
capabilities: [{
securityToken: securityToken,
automationName: 'Appium',
// 3. Set device capabilities.
platformName: 'iOS',
model: 'iPhone.*',
// 4. Set Perfecto Media repository path of App under test.
app: 'PUBLIC:ExpenseTracker/Native/iOS/InvoiceApp1.0.ipa',
// 5. Set the unique identifier of your app
bundleId: 'io.perfecto.expense.tracker',
appiumVersion: '1.20.2',
autoLaunch: true, // Whether to have Appium install and launch the app automatically.
iOSResign: true, // To work with hybrid applications, install the iOS/Android application as instrumented.
// fullReset: false, // Reset app state by uninstalling app
browserName: '',
takesScreenshot: false,
screenshotOnError: true,
openDeviceTimeout: 5
}, ],
// Default timeout for all waitFor* commands.
waitforTimeout: 30000,
// Default timeout in milliseconds for request
// if Selenium Grid doesn't send response
connectionRetryTimeout: 90000,
// Default request retries count
connectionRetryCount: 3,
framework: 'jasmine',
// Options to be passed to Jasmine.
jasmineNodeOpts: {
// Jasmine default timeout
defaultTimeoutInterval: 100000,
// The Jasmine framework allows interception of each assertion in order to log the state of the application
// or website depending on the result. For example, it is pretty handy to take a screenshot every time
// an assertion fails.
expectationResultHandler: function(passed, assertion) {
// do something
}
},
reporters: ['spec'],
//
// =====
// Hooks
// =====
// Gets executed before test execution begins. At this point you can access all global
// variables, such as `browser`. It is the perfect place to define custom commands.
before: function(capabilities, specs) {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
if (process.env.jobName != null) {
reportingClient = new Reporting.Perfecto.PerfectoReportingClient(new Reporting.Perfecto.PerfectoExecutionContext({
webdriver: {
executeScript: (command, params) => {
return browser.execute(command, params);
}
},
job: new Reporting.Model.Job({
jobName: process.env.jobName,
buildNumber: parseInt(process.env.jobNumber)
}),
tags: tags
}));
} else {
reportingClient = new Reporting.Perfecto.PerfectoReportingClient(new Reporting.Perfecto.PerfectoExecutionContext({
webdriver: {
executeScript: (command, params) => {
return browser.execute(command, params);
}
},
tags: tags
}));
}
browser.reportingClient = reportingClient;
var myReporter = {
specStarted: function(result) {
reportingClient.testStart(result.fullName);
},
specDone: async function(result) {
if (result.status === 'failed') {
const failure = await result.failedExpectations[result.failedExpectations.length - 1];
await reportingClient.testStop({
status: Reporting.Constants.results.failed,
message: `${failure.message} ${failure.stack}`
});
} else {
await reportingClient.testStop({
status: Reporting.Constants.results.passed
});
}
}
}
jasmine.getEnv().addReporter(myReporter);
},
// Gets executed after all tests are done. You still have access to all global variables from
// the test.
after: async function(result, capabilities, specs) {
await console.log("\n\nReport: " + browser.capabilities['testGridReportUrl']);
},
}

const path = require('path');
const Reporting = require('perfecto-reporting');
var reportingClient;
//1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
var host = '<<cloud name>>';
// 2. Replace <<security token>> with your perfecto security token.
var securityToken = '<<security token>>';
host = process.env.HOST == null ? host : process.env.HOST;
securityToken = process.env.SECURITY_TOKEN == null ? securityToken : process.env.SECURITY_TOKEN;
//Define your global tags here:
const tags = ['SampleTag1'];
global.STEP_TIMEOUT = 900000;
global.IMPLICIT_TIMEOUT = 5000;
exports.config = {
securityToken: securityToken,
protocol: 'http',
hostname: host + '.perfectomobile.com',
path: '/nexperience/perfectomobile/wd/hub',
port: 80,
sync: true,
bail: 0,
exclude: [],
specs: [
'android/native.js'
],
maxInstances: 1,
capabilities: [{
securityToken: securityToken,
automationName: 'Appium',
// 3. Set device capabilities.
platformName: 'Android',
model: 'Galaxy S.*|LG.*',
// 4. Set Perfecto Media repository path of App under test.
app: 'PUBLIC:ExpenseTracker/Native/android/ExpenseAppVer1.0.apk',
// 5. Set the unique identifier of your app
appPackage: 'io.perfecto.expense.tracker',
autoLaunch: true, // Whether to have Appium install and launch the app automatically.
// fullReset: false, // Reset app state by uninstalling app
browserName: '',
takesScreenshot: false,
screenshotOnError: true,
openDeviceTimeout: 5
}, ],
// Default timeout for all waitFor* commands.
waitforTimeout: 30000,
// Default timeout in milliseconds for request
// if Selenium Grid doesn't send response
connectionRetryTimeout: 90000,
// Default request retries count
connectionRetryCount: 3,
framework: 'jasmine',
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 100000,
// The Jasmine framework allows interception of each assertion in order to log the state of the application
// or website depending on the result. For example, it is pretty handy to take a screenshot every time
// an assertion fails.
expectationResultHandler: function(passed, assertion) {
// do something
}
},
reporters: ['spec'],
//
// =====
// Hooks
// =====
// Gets executed before test execution begins. At this point you can access all global
// variables, such as `browser`. It is the perfect place to define custom commands.
before: function(capabilities, specs) {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
if (process.env.jobName != null) {
reportingClient = new Reporting.Perfecto.PerfectoReportingClient(new Reporting.Perfecto.PerfectoExecutionContext({
webdriver: {
executeScript: (command, params) => {
return browser.execute(command, params);
}
},
job: new Reporting.Model.Job({
jobName: process.env.jobName,
buildNumber: parseInt(process.env.jobNumber)
}),
tags: tags
}));
} else {
reportingClient = new Reporting.Perfecto.PerfectoReportingClient(new Reporting.Perfecto.PerfectoExecutionContext({
webdriver: {
executeScript: (command, params) => {
return browser.execute(command, params);
}
},
tags: tags
}));
}
browser.reportingClient = reportingClient;
var myReporter = {
specStarted: function(result) {
reportingClient.testStart(result.fullName);
},
specDone: async function(result) {
if (result.status === 'failed') {
const failure = await result.failedExpectations[result.failedExpectations.length - 1];
await reportingClient.testStop({
status: Reporting.Constants.results.failed,
message: `${failure.message} ${failure.stack}`
});
} else {
await reportingClient.testStop({
status: Reporting.Constants.results.passed
});
}
}
}
jasmine.getEnv().addReporter(myReporter);
},
// Gets executed after all tests are done. You still have access to all global variables from
// the test.
after: async function(result, capabilities, specs) {
await console.log("\n\nReport: " + browser.capabilities['testGridReportUrl']);
},
}

Prerequisites
Make sure you have installed the following items on your machine:
Download and extract the project
Perform the following steps to extract the project, download it to your machine, and navigate to the CSharp folder.
To download and extract the project:
-
Download the project.
-
Extract the project to your machine.
-
Inside the extracted project, navigate to Appium > Native > CSharp.
-
Launch Visual Studio.
-
In Visual Studio:
-
Click Open a project or solution.
-
Navigate to your project's
UnitTesting.sln
file and open it. -
Right-click Dependencies and select Manage NuGet Packages.
-
On the Browse tab, find and install the Appium.WebDriver and Microsoft.VisualStudio.UnitTesting packages.
-
View the test script
The following code snippet shows the content of the included script, native.cs
.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Support.UI;
using Reportium.Client;
using Reportium.Model;
using Reportium.Test;
using TestContext = Microsoft.VisualStudio.TestTools.UnitTesting.TestContext;
[assembly: Parallelize(Workers = 3, Scope = ExecutionScope.MethodLevel)]
namespace IOS
{
[TestClass]
public class IOSTest
{
public TestContext TestContext { get; set; }
IOSDriver<IOSElement> driver = null;
ReportiumClient reportiumClient = null;
[TestInitialize]
public void BeforeTest()
{
AppiumOptions capabilities = new AppiumOptions();
// 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
String cloudName = "<<cloud name>>";
// 2. Replace <<security token>> with your perfecto security token.
String securityToken = "<<security token>>";
capabilities.AddAdditionalCapability("securityToken", securityToken);
// 3. Set device capabilities.
capabilities.PlatformName = "iOS";
// 4. Set Perfecto Media repository path of App under test.
capabilities.AddAdditionalCapability("app", "PUBLIC:ExpenseTracker/Native/iOS/InvoiceApp1.0.ipa");
// 5. Set the unique identifier of your app
capabilities.AddAdditionalCapability("appPackage", "io.perfecto.expense.tracker");
// Set other capabilities.
capabilities.AddAdditionalCapability("enableAppiumBehavior", true);
capabilities.AddAdditionalCapability("autoLaunch", true); // Whether to install and launch the app automatically.
capabilities.AddAdditionalCapability("iOSResign", true); // Resign with developer certificate
// capabilities.AddAdditionalCapability("fullReset", false); // Reset app state by uninstalling app.
capabilities.AddAdditionalCapability("takesScreenshot", false);
capabilities.AddAdditionalCapability("screenshotOnError", true);
capabilities.AddAdditionalCapability("openDeviceTimeout", 5);
capabilities.AddAdditionalCapability("model", "iPhone.*");
// Initialize the Appium driver
driver = new IOSDriver<IOSElement>(
new Uri(string.Format("https://{0}.perfectomobile.com/nexperience/perfectomobile/wd/hub/fast", cloudName)), capabilities);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
PerfectoExecutionContext perfectoExecutionContext;
if (System.Environment.GetEnvironmentVariable("JOB_NAME") != null)
{
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.WithProject(new Project("My Project", "1.0"))
.WithJob(new Job(System.Environment.GetEnvironmentVariable("JOB_NAME"),
int.Parse(System.Environment.GetEnvironmentVariable("BUILD_NUMBER"))))
.WithWebDriver(driver).Build();
}
else
{
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.WithProject(new Project("My Project", "1.0"))
.WithWebDriver(driver).Build();
}
reportiumClient = PerfectoClientFactory.CreatePerfectoReportiumClient(perfectoExecutionContext);
reportiumClient.TestStart(TestContext.TestName, new Reportium.Test.TestContext("native", "ios"));
}
[TestMethod]
[Description("Native C# iOS Sample1")]
public void CSharpIOSNativeTest1()
{
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
reportiumClient.StepStart("Enter email");
IOSElement email = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_email"))));
email.SendKeys("test@perfecto.com");
reportiumClient.StepStart("Enter password");
IOSElement password = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_password"))));
password.SendKeys("test123");
driver.HideKeyboard();
reportiumClient.StepStart("Click login");
driver.HideKeyboard();
IOSElement login = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_login_btn"))));
login.Click();
reportiumClient.StepStart("Add expense");
IOSElement add = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("list_add_btn"))));
add.Click();
reportiumClient.StepStart("Select head");
IOSElement head = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("edit_head"))));
head.Click();
wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.XPath("//*[@value='- Select -']")))[0].SendKeys("Flight");
reportiumClient.StepStart("Enter amount");
IOSElement amount = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("edit_amount"))));
amount.SendKeys("100");
reportiumClient.StepStart("Save expense");
IOSElement save = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("add_save_btn"))));
save.Click();
reportiumClient.StepStart("Verify alert");
String expectedText = "Please enter valid category";
Boolean res = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@name='" + expectedText + "']"))).Displayed;
reportiumClient.ReportiumAssert("Alert text validation.", res);
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateSuccess());
}
catch (Exception e)
{
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateFailure(e));
}
////Close connection and ends the test
driver.Quit();
Console.WriteLine("C# IOS execution completed");
}
[TestMethod]
[Description("Native C# iOS Sample2")]
public void CSharpIOSNativeTest2()
{
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
reportiumClient.StepStart("Enter email");
IOSElement email = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_email"))));
email.SendKeys("test@perfecto.com");
reportiumClient.StepStart("Enter password");
IOSElement password = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_password"))));
password.SendKeys("test123");
driver.HideKeyboard();
reportiumClient.StepStart("Click login");
IOSElement login = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("login_login_btn"))));
login.Click();
reportiumClient.StepStart("Add expense");
IOSElement add = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("list_add_btn"))));
add.Click();
reportiumClient.StepStart("Select head");
IOSElement head = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("edit_head"))));
head.Click();
wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.XPath("//*[@value='- Select -']")))[0].SendKeys("Flight");
reportiumClient.StepStart("Enter amount");
IOSElement amount = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("edit_amount"))));
amount.SendKeys("100");
reportiumClient.StepStart("Save expense");
IOSElement save = (IOSElement)wait.Until(ExpectedConditions.ElementIsVisible((By.Name("add_save_btn"))));
save.Click();
reportiumClient.StepStart("Verify alert");
String expectedText = "Please enter valid category";
Boolean res = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@name='" + expectedText + "']"))).Displayed;
reportiumClient.ReportiumAssert("Alert text validation.", res);
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateSuccess());
}
catch (Exception e)
{
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateFailure(e));
}
////Close connection and ends the test
driver.Quit();
Console.WriteLine("C# IOS execution completed");
}
}
}

using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Support.UI;
using Reportium.Client;
using Reportium.Model;
[assembly: Parallelize(Workers = 3, Scope = ExecutionScope.MethodLevel)]
namespace Android
{
[TestClass]
public class AndroidTest
{
public TestContext TestContext { get; set; }
AndroidDriver<AndroidElement> driver = null;
ReportiumClient reportiumClient = null;
[TestInitialize]
public void BeforeTest()
{
AppiumOptions capabilities = new AppiumOptions();
// 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
String cloudName = "<<cloud name>>";
// 2. Replace <<security token>> with your perfecto security token.
String securityToken = "<<security token>>";
capabilities.AddAdditionalCapability("securityToken", securityToken);
// 3. Set device capabilities.
capabilities.PlatformName = "Android";
capabilities.AddAdditionalCapability("model", "Galaxy S.*|LG.*");
// 4. Set Perfecto Media repository path of App under test.
capabilities.AddAdditionalCapability("app", "PUBLIC:ExpenseTracker/Native/android/ExpenseAppVer1.0.apk");
// 5. Set the unique identifier of your app
capabilities.AddAdditionalCapability("appPackage", "io.perfecto.expense.tracker");
// Set other capabilities.
capabilities.AddAdditionalCapability("enableAppiumBehavior", true);
capabilities.AddAdditionalCapability("autoLaunch", true); // Whether to install and launch the app automatically.
// capabilities.AddAdditionalCapability("fullReset", false); // Reset app state by uninstalling app.
capabilities.AddAdditionalCapability("takesScreenshot", false);
capabilities.AddAdditionalCapability("screenshotOnError", true);
capabilities.AddAdditionalCapability("openDeviceTimeout", 5);
capabilities.AddAdditionalCapability("model", "Galaxy S.*");
// Initialize the Appium driver
driver = new AndroidDriver<AndroidElement>(
new Uri(string.Format("https://{0}.perfectomobile.com/nexperience/perfectomobile/wd/hub/fast", cloudName)), capabilities);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
PerfectoExecutionContext perfectoExecutionContext;
if (System.Environment.GetEnvironmentVariable("jobName") != null)
{
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.WithProject(new Project("My Project", "1.0"))
.WithJob(new Job(System.Environment.GetEnvironmentVariable("jobName"),
int.Parse(System.Environment.GetEnvironmentVariable("jobNumber"))))
.WithWebDriver(driver).Build();
}
else
{
perfectoExecutionContext = new PerfectoExecutionContext.PerfectoExecutionContextBuilder()
.WithProject(new Project("My Project", "1.0"))
.WithWebDriver(driver).Build();
}
reportiumClient = PerfectoClientFactory.CreatePerfectoReportiumClient(perfectoExecutionContext);
reportiumClient.TestStart(TestContext.TestName, new Reportium.Test.TestContext("native", "android"));
}
[TestMethod]
[Description("Native C# Android Sample1")]
public void PerfectoCSharpAndroidNativeTest1()
{
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
reportiumClient.StepStart("Enter email");
IWebElement email = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_email")));
email.SendKeys("test@perfecto.com");
reportiumClient.StepStart("Enter password");
IWebElement password = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_password")));
password.SendKeys("test123");
reportiumClient.StepStart("Click login");
driver.HideKeyboard();
IWebElement login = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_login_btn")));
login.Click();
reportiumClient.StepStart("Add expense");
IWebElement add = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/list_add_btn")));
add.Click();
reportiumClient.StepStart("Select head");
IWebElement head = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/input_layout_head")));
head.Click();
IWebElement flight = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@text='Flight']")));
flight.Click();
reportiumClient.StepStart("Enter amount");
IWebElement amount = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/add_amount")));
amount.SendKeys("100");
reportiumClient.StepStart("Save expense");
IWebElement save = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/layout_buttons")));
save.Click();
reportiumClient.StepStart("Verify alert");
String expectedText = "Select Currency";
bool res = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@text='" + expectedText + "']"))).Displayed;
reportiumClient.ReportiumAssert("Alert text validation.", res);
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateSuccess());
}
catch (Exception e)
{
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateFailure(e));
}
//Close connection and ends the test
driver.Quit();
Console.WriteLine("C# Android execution completed");
}
[TestMethod]
[Description("Native C# Android Sample2")]
public void PerfectoCSharpAndroidNativeTest2()
{
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
reportiumClient.StepStart("Enter email");
IWebElement email = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_email")));
email.SendKeys("test@perfecto.com");
reportiumClient.StepStart("Enter password");
IWebElement password = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_password")));
password.SendKeys("test123");
reportiumClient.StepStart("Click login");
IWebElement login = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/login_login_btn")));
login.Click();
reportiumClient.StepStart("Add expense");
IWebElement add = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/list_add_btn")));
add.Click();
reportiumClient.StepStart("Select head");
IWebElement head = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/input_layout_head")));
head.Click();
IWebElement flight = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@text='Flight']")));
flight.Click();
reportiumClient.StepStart("Enter amount");
IWebElement amount = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/add_amount")));
amount.SendKeys("100");
reportiumClient.StepStart("Save expense");
IWebElement save = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("io.perfecto.expense.tracker:id/layout_buttons")));
save.Click();
reportiumClient.StepStart("Verify alert");
String expectedText = "Select Currency";
bool res = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@text='" + expectedText + "']"))).Displayed;
reportiumClient.ReportiumAssert("Alert text validation.", res);
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateSuccess());
}
catch (Exception e)
{
reportiumClient.TestStop(Reportium.Test.Result.TestResultFactory.CreateFailure(e));
}
//Close connection and ends the test
driver.Quit();
Console.WriteLine("C# Android execution completed");
}
}
}

Prerequisites
Make sure you have installed the following items on your machine:
-
Python 3+:
-
On Windows: Download and install the latest Python 3.9.x version appropriate for your platform from here.
-
On Mac/Linux: Install the latest Python 3.9.x version from here.
Note:On Windows 7, Python 3.8.x is required. Newer versions are not supported.
-
-
Pip package manager: Follow the official documentation to install pip.
-
Project dependencies: Run the following command from a command line window to install the project dependencies:
-
HTTPS protocol: On Mac only, run the following command from a command line window to allow Python to connect via HTTPS protocol:
Copy/Applications/Python\ <<Python major version>>/Install\ Certificates.command
where
<<Python major version>>
corresponds to the major Python version, for example 3.8.
Download and extract the project
Perform the following steps to extract the project, download it to your machine, and navigate to the Python folder.
To download and extract the project:
-
Download the project.
-
Extract the project to your machine.
-
Inside the extracted project, navigate to Appium > Native > Python.
View the test script
The following code snippet shows the content of the included test script, native.py
.

from appium.webdriver.common.mobileby import MobileBy
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
cloudName = "<<cloud name>>"
capabilities = {
# 2. Replace <<security token>> with your perfecto security token.
'securityToken' : "<<security token>>",
# 3. Set device capabilities.
'platformName': 'iOS',
'manufacturer': 'Apple',
'model': 'iPhone.*',
# 4. Set Perfecto Media repository path of App under test.
'app': 'PUBLIC:ExpenseTracker/Native/iOS/InvoiceApp1.0.ipa',
# 5. Set the unique identifier of your app
'bundleId': 'io.perfecto.expense.tracker',
# Set other capabilities.
'enableAppiumBehavior': True, # Enable new architecture of Appium
'autoLaunch': True, # To work with hybrid applications, install the iOS/Android application as instrumented.
'iOSResign': True, # Resigns using developer certificate
# 'fullReset': false, # Reset app state by uninstalling app
'takesScreenshot': False,
'screenshotOnError': True,
'openDeviceTimeout': 5
}
# Initialize the Appium driver
driver = webdriver.Remote('https://' + cloudName + '.perfectomobile.com/nexperience/perfectomobile/wd/hub', capabilities)
# set implicit wait time
driver.implicitly_wait(5)
# Your code goes here
wait = WebDriverWait(driver, 30)
email = wait.until(EC.presence_of_element_located((MobileBy.NAME, "login_email")))
email.send_keys('test@perfecto.com')
password = wait.until(EC.presence_of_element_located((MobileBy.NAME, "login_password")))
password.send_keys('test123')
login = wait.until(EC.presence_of_element_located((MobileBy.NAME, "login_login_btn")))
login.click()
add = wait.until(EC.presence_of_element_located((MobileBy.NAME, "list_add_btn")))
add.click()
head = wait.until(EC.presence_of_element_located((MobileBy.NAME, "edit_head")))
head.click()
flight = wait.until(EC.presence_of_element_located((MobileBy.XPATH, "//*[@value='- Select -']")))
flight.send_keys("Flight")
amount = wait.until(EC.presence_of_element_located((MobileBy.NAME, "edit_amount")))
amount.send_keys('100')
save = wait.until(EC.presence_of_element_located((MobileBy.NAME, "add_save_btn")))
save.click()
expectedText = "Please enter valid category"
wait.until(EC.presence_of_element_located((MobileBy.XPATH, "//*[@name='"+expectedText+"']")))
#Quits the driver
driver.quit()
print("Python iOS Execution completed")

from appium.webdriver.common.mobileby import MobileBy
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
cloudName = "<<cloud name>>"
capabilities = {
# 2. Replace <<security token>> with your perfecto security token.
'securityToken' : "<<security token>>",
# 3. Set device capabilities.
'platformName': 'Android',
'model': 'Galaxy S.*|LG.*',
# 4. Set Perfecto Media repository path of App under test.
'app': 'PUBLIC:ExpenseTracker/Native/android/ExpenseAppVer1.0.apk',
# 5. Set the unique identifier of your app
'bundleId': 'io.perfecto.expense.tracker',
# Set other capabilities.
'enableAppiumBehavior': True, # Enable new architecture of Appium
'autoLaunch': True, # Whether to have Appium install and launch the app automatically.
# 'fullReset': false, # Reset app state by uninstalling app
'takesScreenshot': False,
'screenshotOnError': True,
'openDeviceTimeout': 5
}
# Initialize the Appium driver
driver = webdriver.Remote('https://' + cloudName + '.perfectomobile.com/nexperience/perfectomobile/wd/hub', capabilities)
# set implicit wait time
driver.implicitly_wait(5)
wait = WebDriverWait(driver, 30)
email = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/login_email")))
email.send_keys('test@perfecto.com')
password = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/login_password")))
password.send_keys('test123')
params = {
'mode': 'off'
}
driver.execute_script('mobile:keyboard:display', params);
login = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/login_login_btn")))
login.click()
add = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/list_add_btn")))
add.click()
head = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/input_layout_head")))
head.click()
flight = wait.until(EC.presence_of_element_located((MobileBy.XPATH, '//*[@text="Flight"]')))
flight.click()
amount = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/add_amount")))
amount.send_keys('100')
save = wait.until(EC.presence_of_element_located((MobileBy.ID, "io.perfecto.expense.tracker:id/layout_buttons")))
save.click()
expectedText = "Select Currency"
wait.until(EC.presence_of_element_located((MobileBy.XPATH, "//*[@text='"+expectedText+"']")))
#Quits the driver
driver.quit()
print("Python Android Execution completed")

Prerequisites
Make sure you have installed the following items on your machine:
- The latest Ruby 2.7 version appropriate for your platform
-
The following RubyGems:
Run the following commands from a command line window:
Copygem install ffi
gem uninstall -aIx eventmachine
gem install eventmachine --platform=ruby
gem install bundler
bundle install
Download and extract the project
Perform the following steps to extract the project, download it to your machine, and navigate to the Ruby folder.
To download and extract the project:
-
Download the project.
-
Extract the project to your machine.
-
Inside the extracted project, navigate to Appium > Native > Ruby.
View the test script
The following code snippet shows the content of the included test script, native.rb
.

require 'perfecto-reporting'
require 'appium_lib'
desired_caps = {
# 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
appium_lib: {
server_url: 'https://%s.perfectomobile.com/nexperience/perfectomobile/wd/hub' % "<<cloud name>>",
},
caps: {
# 2. Replace <<security token>> with your perfecto security token.
securityToken: '<<security token>>',
# 3. Set device capabilities.
platformName: 'iOS',
manufacturer: 'Apple',
model: 'iPhone.*',
# 4. Set Perfecto Media repository path of App under test.
app: 'PUBLIC:ExpenseTracker/Native/iOS/InvoiceApp1.0.ipa',
# 5. Set the unique identifier of your app
bundleId: 'io.perfecto.expense.tracker',
# Set other capabilities.
enableAppiumBehavior: true, # Enable new architecture of Appium
autoLaunch: true, # Whether to have Appium install and launch the app automatically.
iOSResign: true, # Resign with developer certificate
# fullReset: false, # Whether to install and launch the app automatically.
takesScreenshot: false,
screenshotOnError: true,
openDeviceTimeout: 5
}
}
# Initialize the Appium driver
@driver = Appium::Driver.new(desired_caps, true).start_driver
# Setting implicit wait
@driver.manage.timeouts.implicit_wait = 5
# Initialize Smart Reporting
if ENV["jobName"] != nil
perfectoExecutionContext = PerfectoExecutionContext.new(PerfectoExecutionContext::PerfectoExecutionContextBuilder
.withWebDriver(@driver).withJob(Job.new(ENV["jobName"], ENV["jobNumber"].to_i)).build)
else
perfectoExecutionContext = PerfectoExecutionContext.new(PerfectoExecutionContext::PerfectoExecutionContextBuilder
.withWebDriver(@driver).build)
end
@reportiumClient = PerfectoReportiumClient.new(perfectoExecutionContext)
tec = TestContext::TestContextBuilder.build()
@reportiumClient.testStart("Native Ruby iOS Sample", tec)
begin
wait = Selenium::WebDriver::Wait.new(:timeout => 30)
@reportiumClient.stepStart('Enter email')
wait.until{ @driver.find_element(:name => 'login_email') }
@driver.find_element(:name => 'login_email').send_keys('test@perfecto.com')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Enter password')
wait.until{ @driver.find_element(:name => 'login_password').displayed? }
@driver.find_element(:name => 'login_password').send_keys('test123')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Click login')
@driver.hide_keyboard
wait.until{ @driver.find_element(:name => 'login_login_btn').displayed? }
@driver.find_element(:name => 'login_login_btn').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Add expense')
wait.until{ @driver.find_element(:name => 'list_add_btn').displayed? }
@driver.find_element(:name => 'list_add_btn').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Select head')
wait.until{ @driver.find_element(:name => 'edit_head').displayed? }
@driver.find_element(:name => 'edit_head').click
wait.until{ @driver.find_element(:xpath => "//*[@value='- Select -']").displayed? }
@driver.find_element(:xpath => "//*[@value='- Select -']").send_keys("Flight")
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Enter amount')
wait.until{ @driver.find_element(:name => 'edit_amount').displayed? }
@driver.find_element(:name => 'edit_amount').send_keys('100')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Save expense')
wait.until{ @driver.find_element(:name => 'add_save_btn').displayed? }
@driver.find_element(:name => 'add_save_btn').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart("Verify alert");
expectedText = "Please enter valid category"
wait.until{ @driver.find_element(:name => expectedText).displayed? }
@reportiumClient.reportiumAssert(expectedText, @driver.find_element(:name => expectedText).text === expectedText)
@reportiumClient.stepEnd();
@reportiumClient.testStop(TestResultFactory.createSuccess(), tec)
rescue Exception => exception
@exception = exception
@reportiumClient.testStop(TestResultFactory.createFailure(@exception.exception.message, @exception.exception, nil), tec)
raise exception
ensure
# Prints the report url
puts 'Report url - ' + @reportiumClient.getReportUrl
#Quits the driver
@driver.quit
puts "Ruby iOS Execution completed"
end

require 'perfecto-reporting'
require 'appium_lib'
desired_caps = {
# 1. Replace <<cloud name>> with your perfecto cloud name (e.g. demo is the cloudName of demo.perfectomobile.com).
appium_lib: {
server_url: 'https://%s.perfectomobile.com/nexperience/perfectomobile/wd/hub' % "<<cloud name>>",
},
caps: {
# 2. Replace <<security token>> with your perfecto security token.
securityToken: '<<security token>>',
# 3. Set device capabilities.
platformName: 'Android',
model: 'Galaxy S.*|LG.*',
# 4. Set Perfecto Media repository path of App under test.
app: 'PUBLIC:ExpenseTracker/Native/android/ExpenseAppVer1.0.apk',
# 5. Set the unique identifier of your app
appPackage: 'io.perfecto.expense.tracker',
# Set other capabilities.
enableAppiumBehavior: true, # Enable new architecture of Appium
autoLaunch: true, # Whether to have Appium install and launch the app automatically.
# fullReset: false, # Reset app state by uninstalling app
takesScreenshot: false,
screenshotOnError: true,
openDeviceTimeout: 5
}
}
# Initialize the Appium driver
@driver = Appium::Driver.new(desired_caps, true).start_driver
# Setting implicit wait
@driver.manage.timeouts.implicit_wait = 5
# Initialize Smart Reporting
if ENV["jobName"] != nil
perfectoExecutionContext = PerfectoExecutionContext.new(PerfectoExecutionContext::PerfectoExecutionContextBuilder
.withWebDriver(@driver).withJob(Job.new(ENV["jobName"], ENV["jobNumber"].to_i)).build)
else
perfectoExecutionContext = PerfectoExecutionContext.new(PerfectoExecutionContext::PerfectoExecutionContextBuilder
.withWebDriver(@driver).build)
end
@reportiumClient = PerfectoReportiumClient.new(perfectoExecutionContext)
tec = TestContext::TestContextBuilder.build()
@reportiumClient.testStart("Native Ruby Android Sample", tec)
begin
wait = Selenium::WebDriver::Wait.new(:timeout => 30)
@reportiumClient.stepStart('Enter email')
wait.until{ @driver.find_element(:id => 'login_email') }
@driver.find_element(:id => 'login_email').send_keys('test@perfecto.com')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Enter password')
wait.until{ @driver.find_element(:id => 'login_password').displayed? }
@driver.find_element(:id => 'login_password').send_keys('test123')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Click login')
@driver.hide_keyboard
wait.until{ @driver.find_element(:id => 'login_login_btn').displayed? }
@driver.find_element(:id => 'login_login_btn').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Add expense')
wait.until{ @driver.find_element(:id => 'list_add_btn').displayed? }
@driver.find_element(:id => 'list_add_btn').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Select head')
wait.until{ @driver.find_element(:id => 'input_layout_head').displayed? }
@driver.find_element(:id => 'input_layout_head').click
wait.until{ @driver.find_element(:xpath => "//*[@text='Flight']").displayed? }
@driver.find_element(:xpath => "//*[@text='Flight']").click
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Enter amount')
wait.until{ @driver.find_element(:id => 'add_amount').displayed? }
@driver.find_element(:id => 'add_amount').send_keys('100')
@reportiumClient.stepEnd()
@reportiumClient.stepStart('Save expense')
wait.until{ @driver.find_element(:id => 'add_save_btn').displayed? }
@driver.find_element(:id => 'layout_buttons').click
@reportiumClient.stepEnd()
@reportiumClient.stepStart("Verify alert");
expectedText = "Select Currency"
wait.until{ @driver.find_element(:xpath => "//*[@text='"+expectedText+"']").displayed? }
@reportiumClient.reportiumAssert(expectedText, @driver.find_element(:xpath => "//*[@text='"+expectedText+"']").text === expectedText)
@reportiumClient.stepEnd();
@reportiumClient.testStop(TestResultFactory.createSuccess(), tec)
rescue Exception => exception
@exception = exception
@reportiumClient.testStop(TestResultFactory.createFailure(@exception.exception.message, @exception.exception, nil), tec)
raise exception
ensure
# Prints the report url
puts 'Report url - ' + @reportiumClient.getReportUrl
#Quits the driver
@driver.quit
puts "Ruby Android Execution completed"
end